/*!
 * QuantumUI Free v1.0.0 (http://quantumui.org)
 * Copyright 2014-2015 Mehmet Otkun, quantumui.org
 */

/*!
 * QuantumUI Free v1.0.0 (http://quantumui.org)
 * Copyright 2014-2015 Mehmet Otkun, quantumui.org
 */
(function (window, angular, undefined) {
	'use strict';
	if (typeof jQuery != 'undefined')
		return
	var vdoc = window.document, elproto = window.Element.prototype;
	try {
		vdoc.querySelector(':scope body');
	} catch (err) { // polyfill native methods if it doesn't
		['querySelector', 'querySelectorAll'].forEach(function (method) {
			var native = elproto[method];
			elproto[method] = function (selectors) {
				if (/(^|,)\s*:scope/.test(selectors)) {
					var id = this.id, result;
					this.id = 'ID_' + Date.now();
					selectors = selectors.replace(/((^|,)\s*):scope/g, '$1#' + this.id);
					result = vdoc[method](selectors);
					this.id = id;
					return result;
				}
				else
					return native.call(this, selectors);
			}
		});
	};


	var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g,
		MOZ_HACK_REGEXP = /^moz([A-Z])/;
	function camelCase(name) {
		return name.
			replace(SPECIAL_CHARS_REGEXP, function (_, separator, letter, offset) {
				return offset ? letter.toUpperCase() : letter;
			}).
			replace(MOZ_HACK_REGEXP, 'Moz$1');
	};
	var cssNumber = {
		"columnCount": true,
		"fillOpacity": true,
		"flexGrow": true,
		"flexShrink": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"order": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": true
	};
	function trimStart(str) {
		while (str && str.length && str.charAt[0] === ' ') {
			str = str.slice(1, str.length - 1)
		}
		return str;
	};
	function getStyles(elem) {
		if (!(elem instanceof HTMLElement))
			return {};

		if (elem.ownerDocument && elem.ownerDocument.defaultView.opener) {
			return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
		}
		if (elem instanceof HTMLElement)
			return window.getComputedStyle(elem, null);
		else
			return {};
	};
	var isDefined = angular.isDefined;
	var forEach = angular.forEach;

	var iframe,
		elemdisplay = {
			HTML: "block",
			BODY: "block"
		};
	var cssValue = function (name, value) {
		if (angular.isNumber(value) && !cssNumber[name])
			value = value + 'px';
		return value;
	};
	var checkParentNode = function (parent, child) {
		if (parent === child)
			return true;
		if (child.path) {
			var length = child.path.length, node = child.path[1], index = 1, has = false;
			while (!has && index < length) {
				if (node === parent)
					has = true;
				index++;
				node = child.path[index]
			}
			return has;
		}
		else {
			var node = child.parentNode;
			while (node !== null) {
				if (node == parent) {
					return true;
				}
				node = node.parentNode;
			}
		}

		return false;
	};
	var setOffset = function (elem, options, i) {

		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
			computed = getStyles(elem);
		var position = computed.position,
			curElem = angular.element(elem),
			props = {};
		if (position === "static") {
			elem.style.position = "relative";
		}

		curOffset = curElem.offset();
		curCSSTop = computed.top;
		curCSSLeft = computed.left;
		calculatePosition = (position === "absolute" || position === "fixed") &&
			(curCSSTop + curCSSLeft).indexOf("auto") > -1;
		if (calculatePosition) {
			curPosition = getPosition(elem);
			curTop = curPosition.top;
			curLeft = curPosition.left;

		} else {
			curTop = parseFloat(curCSSTop) || 0;
			curLeft = parseFloat(curCSSLeft) || 0;
		}

		if (angular.isFunction(options)) {
			options = options.call(elem, i, angular.extend({}, curOffset));
		}

		if (options.top !== null) {
			props.top = (options.top - curOffset.top) + curTop;
		}
		if (options.left !== null) {
			props.left = (options.left - curOffset.left) + curLeft;
		}

		if ("using" in options) {
			options.using.call(elem, props);

		} else {
			elem.style.top = props.top + 'px';
			elem.style.left = props.left + 'px';
		}
	};
	var getPosition = function (elem) {
		if (!elem) {
			return;
		}

		var offsetParent, offset,
			parentOffset = { top: 0, left: 0 },
			computed = getStyles(elem),
			CSSposition = computed.position,
			curElem = angular.element(elem);
		if (CSSposition === "fixed") {
			offset = elem.getBoundingClientRect();

		} else {
			offsetParent = getOffsetParent(elem);
			offset = curElem.offset();
			if (!nodeName(offsetParent, "html")) {
				parentOffset = angular.extend(parentOffset, angular.element(offsetParent).offset());

			}
			var computedParent = getStyles(offsetParent);
			parentOffset.top += parseInt(computedParent.borderTopWidth, 0);
			parentOffset.left += parseInt(computedParent.borderLeftWidth, 0);
		}
		return {
			top: offset.top - parentOffset.top - parseInt(computed.marginTop, 0),
			left: offset.left - parentOffset.left - parseInt(computed.marginLeft, 0)
		};
	};
	var getOffsetParent = function (elem) {
		var docElem = window.document.documentElement, that = elem[0] ? elem[0] : elem;
		var offsetParent = that && that.offsetParent || docElem,
			computed = getStyles(that);

		while (offsetParent && (!nodeName(offsetParent, "html") &&
			computed.position === "static")) {
			offsetParent = offsetParent.offsetParent;
		}

		return offsetParent || docElem;
	};
	var closest = function (elem, selector) {
		elem = elem.parentNode;
		var matchesSelector = matchesSelectors(elem);
		while (elem && elem.nodeType < 11 && elem.nodeType === 1) {
			if (matchesSelector.call(elem, selector)) {
				return elem;
				break;
			} else {
				elem = elem.parentNode;
			}
		}
		return false;
	};
	var matchesSelectors = function (elem) {
		return elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector;
	};
	var nodeName = function (elem, name) {
		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
	};
	var dir = function (elem, node) {
		var matched = [];
		while (elem && (elem = elem[node]) && elem.nodeType !== 9) {
			if (elem.nodeType === 1) {
				matched.push(elem);
			}
		}
		return matched;
	};
	var sibling = function (cur, dir) {
		while ((cur = cur[dir]) && cur.nodeType !== 1) { }
		return cur;
	};
	var showHide = function (elements, show) {
		var display, elem, hidden,
			values = [],
			index = 0,
			length = elements.length;

		for (; index < length; index++) {
			elem = elements[index];
			if (!elem.style) {
				continue;
			}
			var $elem = angular.element(elem), dataPriv = $elem.data();
			values[index] = dataPriv["olddisplay"];
			display = elem.style.display;
			if (show) {
				if (!values[index] && display === "none") {
					elem.style.display = "";
				}
				if (elem.style.display === "" && isHidden(elem)) {
					values[index] = defaultDisplay(elem.nodeName);
					$elem.data(
						"olddisplay",
						values[index]
					);
				}
			} else {
				hidden = isHidden(elem);

				if (display !== "none" || !hidden) {
					$elem.data(
						"olddisplay",
						hidden ? display : $elem.css("display")
					);
				}
			}
		}
		for (index = 0; index < length; index++) {
			elem = elements[index];
			if (!elem.style) {
				continue;
			}
			if (!show || elem.style.display === "none" || elem.style.display === "") {
				elem.style.display = show ? values[index] || "" : "none";
			}
		}

		return elements;
	};
	var isHidden = function (elem, el) {
		elem = el || elem;
		return angular.element(elem).css("display") === "none" ||
			!angular.contains(elem.ownerDocument, elem);
	};
	var actualDisplay = function (name, doc) {
		var elem = angular.element(doc.createElement(name)).appendTo(doc.body),
			display = elem.css("display");
		elem.detach();

		return display;
	};

	var defaultDisplay = function (nodeName) {
		var doc = document,
			display = elemdisplay[nodeName];

		if (!display) {
			display = actualDisplay(nodeName, doc);
			if (display === "none" || !display) {
				iframe = (iframe || angular.element("<iframe frameborder='0' width='0' height='0'/>"))

				angular.element('body').append(iframe)
				doc = (iframe[0].contentWindow || iframe[0].contentDocument).document;
				doc.write();
				doc.close();

				display = actualDisplay(nodeName, doc);
				iframe.detach();
			}
			elemdisplay[nodeName] = display;
		}
		return display;
	};

	var getWindow = function (elem) {
		return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
	};
	var isWindow = function (obj) {
		return obj !== null && obj === obj.window;
	};
	var getUnique = function (arr) {
		var u = {}, a = [];
		for (var i = 0, l = arr.length; i < l; ++i) {
			if (a.indexOf(arr[i]) === -1) {
				a.push(arr[i]);
			}
		}
		return a;
	};
	var manuplate = function (elem, selector, original) {
		var elems,
			ret = [],
			insert = angular.element(selector),
			last = insert.length - 1,
			i = 0;

		for (; i <= last; i++) {
			elems = i === last ? elem : elem.clone();

			angular.element(insert[i])[original](elems);

			ret.push.apply(ret, elems.slice());

		}
		return elem.pushStack(ret);
	};
	var filterVisible = function (selector) {
		var elems = angular.element(selector.indexOf(':visible')[0]);
		return elems.is(":visible");
	};
	function applyDimension(elem, dimension, show, time, callback) {
		var dimProp = dimension === 'width' ? 'clientWidth' : 'clientHeight',
			$elm = angular.element(elem),
			size = $elm[dimension](),
			hasStyle = angular.isDefined(elem.style[dimension]);
		time = time && (angular.isNumber(time) ? time : isNaN(parseInt(time)) ? 600 : parseInt(time)) || 600;
		var style = {
			position: elem.style.position || '',
			visibilty: elem.style.visiblity || '',
			display: elem.style.display || '',
			overflow: elem.style.overflow || '',
		}
		style[dimension] = elem.style[dimension];
		if (show) {
			$elm.css({ 'visibilty': 'hidden' });
			$elm.css('display', 'block');
			size = $elm[dimension]();
			$elm.css(style);
		}

		!size && (size = 2)
		var unitSize = 10,
			lastSize = show ? 0 : size;
		var start = (new Date()).getTime();
		$elm.css('overflow', 'hidden')
		$elm[dimension](lastSize);
		var i = 1;
		var interval = setInterval(function () {
			var now = (new Date()).getTime();
			unitSize = (size / (time / ((now - start) / i) || 1));
			$elm[dimension](lastSize);
			lastSize = show ? (lastSize + unitSize) : lastSize - unitSize;
			i++;
			if ((now - start) >= time) {
				clearInterval(interval);
				interval = null;
				$elm.css(style);
				callback && callback();
			}
		}, 1);

		setTimeout(function () {
			interval && clearInterval(interval);
		}, time * 2)
	}
	function selectResult(elem, selector) {
		if (elem.length == 1)
			return elem[0].querySelectorAll(selector);
		else {
			var mathches = [];
			forEach(elem, function (elm) {
				var nodes = angular.element(elm.querySelectorAll(selector));
				mathches.push.apply(mathches, nodes.slice());

			})
			return mathches;

		}

	}
	var jqLite = angular.element;
	angular.merge = function (first, second) {
		var len = second && +second.length || 0,
			j = 0,
			i = first && first.length || 0;

		for (; j < len; j++) {
			first[i++] = second[j];
		}

		first.length = i;

		return first;
	};
	angular.map = function (elems, callback, arg) {
		var value,
			i = 0,
			length = elems.length,
			isArray = angular.isArray(elems),
			ret = [];
		if (isArray) {
			for (; i < length; i++) {
				value = callback(elems[i], i, arg);

				if (value !== null) {
					ret.push(value);
				}
			}
		} else {
			for (i in elems) {
				value = callback(elems[i], i, arg);

				if (value !== null) {
					ret.push(value);
				}
			}
		}
		return [].concat.apply([], ret);
	};
	angular.contains = function (a, b) {
		var adown = a.nodeType === 9 ? a.documentElement : a,
			bup = b && b.parentNode;
		return a === bup || !!(bup && bup.nodeType === 1 && angular.contains(adown, bup));
	};

	jqLite.prototype.width = function (value) {
		if (angular.isDefined(value)) {
			return this.innerWidth(value)
		} else {
			var el = this[0];
			var computedStyle = getStyles(el);
			var width = el.offsetWidth;
			if (computedStyle)
				width -= parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
			return width;
		}
	};
	jqLite.prototype.innerWidth = function (value) {
		if (angular.isDefined(value)) {
			(this[0].style.width = angular.isNumber(value) ? (value + 'px') : value);
			return this;
		}
		return this[0].clientWidth;
	};
	jqLite.prototype.outerWidth = function (outer) {
		var el = this[0];
		var value = el.offsetWidth;
		if (outer) {
			var computedStyle = getStyles(el);
			value += parseFloat(computedStyle.marginLeft) + parseFloat(computedStyle.marginRight);
		}
		return value;
	};

	jqLite.prototype.height = function (value) {
		if (angular.isDefined(value)) {
			return this.innerHeight(value)
		} else {
			var el = this[0];
			var computedStyle = getStyles(el);
			var height = el.clientHeight;
			if (computedStyle)
				height -= parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom);
			return height;
		};
	};
	jqLite.prototype.innerHeight = function (value) {
		if (angular.isDefined(value)) {
			(this[0].style.height = angular.isNumber(value) ? (value + 'px') : value);
			return this;
		}
		return this[0].clientHeight;
	};
	jqLite.prototype.outerHeight = function (margin) {
		var el = this[0];
		var value = el.offsetHeight;
		if (margin) {
			var computedStyle = getStyles(el);
			value += parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom);
		}
		return value;
	};
	var _css = jqLite.prototype.css;
	jqLite.prototype.css = function (name, value) {
		var that = this;
		if (angular.isString(name) && isDefined(value)) {
			_css.call(that, name, cssValue(camelCase(name), value))
		}
		else if (angular.isString(name) && that.length) {
			return getStyles(that[0])[camelCase(name)];
		}
		else if (angular.isObject(name)) {
			for (var o in name) {
				_css.call(that, o, cssValue(camelCase(o), name[o]))
			}
		}
		return this;
	};

	jqLite.prototype.first = function () {
		return this.eq(0);
	};
	jqLite.prototype.last = function () {
		return this.eq(-1);
	};
	jqLite.prototype.pushStack = function (elems) {
		var ret = angular.merge(angular.element(), elems);
		ret.prevObject = this;
		ret.context = this.context;
		return ret;
	};

	jqLite.prototype.is = function (name) {
		var el = angular.element(this[0]);
		if (!isDefined(name) || !this.length)
			return false;
		if (angular.isFunction(name))
			return name(this[0]);
		if (angular.isString(name)) {
			if (name.substring(0, 1) == ':') {
				var bool = /^(?:checked|selected|disabled|multiple|readonly|required)$/i;
				if (bool.test(name))
					return angular.isDefined(el.attr((name.substring(1, name.length)).replace(/\ /g, ''))) ? true : false;
				else if (/:visible|:hidden/.test(name)) {
					var visible = angular.contains(el[0].ownerDocument, el) || (el.css('display') === 'none' || el.css('visibilty') === 'hidden') ? false : true;
					return name === ':visible' ? visible : !visible;
				}
			}
			else {
				return this[0].tagName.toLowerCase() == name.replace(/\ /g, '').toLowerCase() || false;
			}
		}
	};
	jqLite.prototype.find = function (selector) {
		var context = this[0];
		if (!context || (context.nodeType !== 1 && context.nodeType !== 9) || !angular.isString(selector)) {
			return [];
		}
		var matches = [];
		if (selector.charAt(0) === '>')
			selector = ':scope ' + selector;
		if (selector.indexOf(':visible') > -1) {
			var elems = angular.element(selectResult(this, selector.split(':visible')[0]))

			forEach(elems, function (val, i) {
				if (angular.element(val).is(':visible'))
					matches.push(val);
			})

		} else {
			matches = selectResult(this, selector)
		}

		if (matches.length) {
			if (matches.length == 1)
				return angular.element(matches[0])
			else {
				return this.pushStack(matches)
			}
		}
		return angular.element();
	};
	jqLite.prototype.has = function (node) {
		if (angular.isString(node)) {
			return this.find(node).length;
		} else {
			var el = node instanceof HTMLElement ? node : angular.isElement(node) && node.length ? node[0] : undefined;
			if (el)
				return checkParentNode(this[0], el);
		}
		return false;
	};

	jqLite.prototype.closest = function (selector) {
		if (!this.length)
			return angular.element();
		var matches = [];
		forEach(this, function (val, i) {
			var node = closest(val, selector);
			if (node)
				matches.push(node);
		})
		return this.pushStack(matches)
	};
	jqLite.prototype.before = function (selector) {
		var that = this;
		var before = angular.isElement(selector) ? selector : angular.element(selector);
		that.after(before);
		before.after(that)


		return this;
	};
	jqLite.prototype.index = function (elem) {
		if (!elem) {
			return (this[0] && this[0].parentNode) ? this.first().prevAll().length : -1;
		}
		if (angular.isString(elem)) {
			return angular.element(elem).indexOf(this[0]);
		}
		return this.indexOf(angular.isElement(elem) ? elem[0] : elem);
	};
	forEach({
		prev: function (elem) {
			return sibling(elem, "previousSibling");
		},
		nextAll: function (elem) {
			return dir(elem, "nextSibling");
		},
		prevAll: function (elem) {
			return dir(elem, "previousSibling");
		}
	}, function (fn, name) {
		jqLite.prototype[name] = function () {
			var matched = angular.map(this, fn);

			if (this.length > 1) {
				if (name == 'prev') {
					matched = getUnique([]);
					matched.reverse();
				}
			}

			return this.pushStack(matched);
		};
	});
	forEach({
		appendTo: "append",
		prependTo: "prepend",
		insertBefore: "before",
		insertAfter: "after",
		replaceAll: "replaceWith"
	}, function (original, name) {

		jqLite.prototype[name] = function (selector) {
			return manuplate(this, selector, original)
		};
	});

	jqLite.prototype.offset = function (options) {
		if (arguments.length) {
			return options === undefined ?
				this :
				forEach(this, function (val, i) {
					setOffset(val, options, i);
				});
		}
		var docElem, win,
			elem = this[0],
			box = { top: 0, left: 0 },
			doc = elem && elem.ownerDocument;

		if (!doc) {
			return;
		}

		docElem = doc.documentElement;
		if (!angular.contains(docElem, elem)) {
			return box;
		}

		box = elem.getBoundingClientRect();
		win = getWindow(doc);
		return {
			top: box.top + win.pageYOffset - docElem.clientTop,
			left: box.left + win.pageXOffset - docElem.clientLeft
		};
	};
	jqLite.prototype.offsetParent = function () {
		return angular.element(getOffsetParent(this));
	};
	jqLite.prototype.position = function () {
		return getPosition(this[0]);
	};
	forEach({ scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function (prop, method) {
		var top = "pageYOffset" === prop;
		jqLite.prototype[method] = function (val) {
			var elem = this;
			var win = getWindow(elem);

			if (val === undefined) {
				return win ? win[prop] : elem[method]();
			}
			if (win) {
				win.scrollTo(
					!top ? val : window.pageXOffset,
					top ? val : window.pageYOffset
				);

			} else {
				elem[0][method] = val;
			}
			return this;
		};
	});
	jqLite.prototype.show = function () {
		return showHide(this, true);
	};
	jqLite.prototype.hide = function () {
		return showHide(this);
	};
	jqLite.prototype.toggle = function (state) {
		if (typeof state === "boolean") {
			return state ? this.show() : this.hide();
		}

		forEach(this, function (val) {
			if (isHidden(val)) {
				angular.element(val).show();
			} else {
				angular.element(val).hide();
			}
		});
		return this;
	}
	jqLite.prototype.slice = function () {
		return this.pushStack([].slice.apply(this, arguments));
	};
	jqLite.prototype.focus = function () {
		var that = this;
		forEach(that, function (node) {
			node.focus();
		})
	};
	jqLite.prototype.blur = function () {
		var that = this;
		forEach(that, function (node) {
			node.blur();
		});
	};
	var _html = jqLite.prototype.html;
	jqLite.prototype.html = function (value) {
		if (!angular.isDefined(value))
			return this[0].innerHTML || this[0].innerText;
		if (angular.isElement(value) || navigator.appVersion.indexOf("MSIE 9.") != -1) {
			_html.call(this, '')
			this.append(value)
		} else {
			_html.call(this, value);
		}

		return this;
	};
	var _on = jqLite.prototype.on;
	jqLite.prototype.on = function (type, handler) {
		if (type.indexOf(' ') > -1 || type.indexOf('.') == -1)
			return _on.call(this, type, handler);
		var namespaces = type.split('.'), nsEvents = window.namespaces = window.namespaces || {};
		type = namespaces.shift();
		namespaces.sort();
		var key = namespaces.join("_"),
			handlers = nsEvents[key] || [];
		handlers.push(handler);
		nsEvents[key] = handlers;
		return _on.call(this, type, handler);
	};
	var _off = jqLite.prototype.off;
	jqLite.prototype.off = function (type, handler) {
		if (!type || type.indexOf(' ') > -1 || type.indexOf('.') == -1)
			return _off.call(this, type, handler)
		var that = this, namespaces = type.split('.'),
			nsEvents = window.namespaces = window.namespaces || {};
		type = namespaces.shift();
		namespaces.sort();
		var prefix = namespaces.join("_");
		forEach(nsEvents, function (handlers, key) {
			if (key.indexOf(prefix) > -1) {
				if (handler) {
					nsEvents[key].splice(handlers.indexOf(handler), 1)
					return _off.call(that, type, handler)
				}
				forEach(handlers, function (hdlr, idx) {
					delete nsEvents[key]
					return _off.call(that, type, hdlr)
				})
			}
		});
		return _off.call(this, type, handler);
	};
	jqLite.prototype.parents = function () {
		return angular.element(dir(this[0], "parentNode"));
	};
	jqLite.prototype.siblings = function () {
		var children = this.parent().children(), that = this;
		var matches = [];
		forEach(children, function (el) {
			if (el != that[0])
				matches.push(el)
		})
		return angular.element(that[0]).pushStack(matches);
	};
	jqLite.prototype.get = function (num) {
		return num !== null ?
			(num < 0 ? this[num + this.length] : this[num]) :
			[].slice.call(this);
	};
	jqLite.prototype.add = function (selector, context) {
		var that = this;
		return this.pushStack(getUnique((angular.merge(that[0], angular.element(selector, context)))));
	};
	jqLite.prototype.slideDown = function (time, callback) {
		forEach(this, function (elem) {
			applyDimension(elem, 'height', true, time, callback)
		})
		return this;
	};
	jqLite.prototype.slideUp = function (time, callback) {
		forEach(this, function (elem) {
			applyDimension(elem, 'height', false, time, callback)
		})
		return this;
	};
	var _jqLite = angular.element;
	function JQLite(element) {
		if (angular.isString(element)) {
			element = trimStart(element);
			if (element.charAt(0) !== '<') {
				if (element.indexOf(':visible') > -1)
					return filterVisible(element);
				element = document.querySelectorAll(element);
			}
		}
		return _jqLite(element);
	};
	angular.element = JQLite;
	angular.element = angular.extend(angular.element, _jqLite);
	angular.element.prototype = _jqLite.prototype;

})(window, window.angular);
if (!String.prototype.trim) {
	String.prototype.trim = function () {
		return this.replace(/^\s+|\s+$/g, '');
	};
};
String.prototype.trimEnd = function (c) {
	var that = this.trim();
	if (c == null || c == "" || c.length > 1 || that.length < 2)
		return that;
	var s = that.slice(that.length - 1, that.length);
	if (s == c)
		return that.slice(0, this.length - 1);
	else
		return that;
};
String.prototype.trimStart = function (c) {
	var that = this.trim();
	if (c == null || c == "" || c.length > 1 || that.length < 2)
		return that;
	var s = that.slice(0, 1);
	if (s == c)
		return that.slice(1, that.length);
	else
		return that;
};
String.prototype.capitaliseFirstLetter = function () {
	return this.charAt(0).toUpperCase() + this.slice(1);
};
if (typeof String.prototype.endsWith !== 'function') {
	String.prototype.endsWith = function (suffix) {
		return this.indexOf(suffix, this.length - suffix.length) !== -1;
	};
};
String.prototype.toTitleCase = function (str) {
	var str = this || '';
	return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
};
String.prototype.replaceAll = function (find, replace) {
	var str = this || '';
	return str.replace(new RegExp(find, 'g'), replace);
};
if (typeof String.prototype.startsWith != 'function') {
	String.prototype.startsWith = function (str) {
		return this.slice(0, str.length) == str;
	};
};
if (typeof String.prototype.endsWith != 'function') {
	String.prototype.endsWith = function (str) {
		return this.slice(-str.length) == str;
	};
};
window.addResizeEvent = function (callback) {
	if (window.addEventListener) {
		window.addEventListener('resize', callback, true);
	}
	else if (window.attachEvent) {
		window.attachEvent('onresize', callback);
	}
};

+function (window, angular, undefined) {
	'use strict';
	var $$raf =
		window.requestAnimationFrame ||
		window.webkitRequestAnimationFrame ||
		window.mozRequestAnimationFrame ||
		window.oRequestAnimationFrame ||
		window.msRequestAnimationFrame ||
		function (callback) {
			setTimeout(function () {
				callback.call(null, false)
			}, 150);
		};
	angular.element.prototype.removeClasses = function (classList) {
		var el = this;
		var list = angular.isArray(classList) ? classList : angular.isStrign(classList) ? classList.split(" ") : [];
		angular.forEach(list, function (val, key) {
			val && el.removeClass(val);
		})
		return this;
	}


	angular.element.prototype.animationEnd = function (callback) {
		var el = this;
		el.one('animationend webkitAnimationEnd oAnimationEnd oanimationend MSAnimationEnd',
			function (evt) {
				callback(evt);
			});
		$$raf(function (evt) {
			if (evt === false)
				callback(evt);
		})
		return this;
	}
	angular.element.prototype.transitionEnd = function (callback) {
		var el = this;

		el.one('transitionend webkitTransitionEnd oTransitionEnd otransitionend',
			function (evt) {
				callback(evt);
			});
		$$raf(function (evt) {
			if (evt === false)
				callback(evt);
		})
		return this;
	}
	var nqCoreApp = angular.module('ngQuantum.directives', [])
	angular.forEach(['Append', 'Prepend', 'Bind'], function (directive) {
		nqCoreApp.directive('nq' + directive, ['$compile', function ($compile) {
			return {
				restrict: 'A',
				link: function (scope, element, attr) {
					var dirName = 'nq' + directive;
					element.addClass('nq-' + directive.toLowerCase()).data('$nqbind', attr[dirName]);
					scope.$watch(attr[dirName], function (value) {
						ensureElement(value);
					});
					function bindElement(value) {
						switch (dirName) {
							case 'nqAppend':
								element.append(value)
								break;
							case 'nqPrepend':
								element.prepend(value)
								break;
							case 'nqBind':
								element.html('')
								element.append(value)
								break;
						}
					}
					function ensureElement(value) {
						if (angular.isElement(value))
							bindElement(value);
						else {
							if (angular.isString(value)) {
								if (value.indexOf('{{') > -1 || value.indexOf('ng-bind') > -1) {
									var complied = angular.element(value);
									$compile(complied)(scope)
									bindElement(complied);
								}
								else if (value.indexOf('</') > -1 && value.indexOf('>') > -1)
									bindElement(angular.element(value));
								else
									bindElement(value);
							}
						}
					}
				}
			}
		}]);
	})
}(window, window.angular);


angular.module('ngQuantum.services.color', ['ngQuantum.services.helpers'])
	.factory('$color', ['$helpers', function ($helpers) {
		var color = {};
		color.value = {
			h: 1,
			s: 1,
			b: 1,
			a: 1
		}
		color.setColor = function (val) {
			if (val) {
				val = val.toLowerCase();
				for (var key in $helpers.stringParsers) {
					if ($helpers.stringParsers.hasOwnProperty(key)) {
						var parser = $helpers.stringParsers[key];
						var match = parser.re.exec(val),
							values = match && parser.parse(match);
						if (values) {
							color.value = color.RGBtoHSB.apply(null, values);

						}
					}
				}
			}
			return color;
		}
		color.RGBtoHSB = function (r, g, b, a) {
			r /= 255;
			g /= 255;
			b /= 255;

			var H, S, V, C;
			V = Math.max(r, g, b);
			C = V - Math.min(r, g, b);
			H = (C === 0 ? null :
				V === r ? (g - b) / C :
					V === g ? (b - r) / C + 2 :
						(r - g) / C + 4
			);
			H = ((H + 360) % 6) * 60 / 360;
			S = C === 0 ? 0 : C / V;
			return { h: H || 1, s: S, b: V, a: a || 1 };
		}
		color.setHue = function (h) {
			color.value.h = h == 0 ? 0 : h == 1 ? 1 : h % 1;
		}
		color.setSaturation = function (s) {
			color.value.s = s == 0 ? 0 : s == 1 ? 1 : s % 1;
		}
		color.setLightness = function (b) {
			color.value.b = b == 0 ? 0 : b == 1 ? 1 : b % 1;
		}
		color.setAlpha = function (a) {
			color.value.a = parseInt((a == 0 ? 0 : a == 1 ? 1 : a % 1) * 100, 10) / 100;
		}
		color.toRGB = function (h, s, b, a) {
			if (!h) {
				h = color.value.h;
				s = color.value.s;
				b = color.value.b;
			}
			h *= 360;
			var R, G, B, X, C;
			h = (h % 360) / 60;
			C = b * s;
			X = C * (1 - Math.abs(h % 2 - 1));
			R = G = B = b - C;

			h = ~~h;
			R += [C, X, 0, 0, X, C][h];
			G += [X, C, C, X, 0, 0][h];
			B += [0, 0, X, C, C, X][h];
			return {
				r: Math.round(R * 255),
				g: Math.round(G * 255),
				b: Math.round(B * 255),
				a: a || color.value.a
			};
		}
		color.toHex = function (h, s, b, a) {
			var rgb = color.toRGB(h, s, b, a);
			return '#' + ((1 << 24) | (parseInt(rgb.r, 10) << 16) | (parseInt(rgb.g, 10) << 8) | parseInt(rgb.b, 10)).toString(16).substr(1);
		}
		color['rgb'] = function () {
			var rgb = color.toRGB();
			return 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
		}
		color['rgba'] = function () {
			var rgb = color.toRGB();
			return 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + rgb.a + ')';
		}
		color['hex'] = function () {
			return color.toHex();
		}
		return color;
	}])
'use strict';
angular.module('ngQuantum.services.helpers', [])
	.factory('$helpers', ['$injector', '$window', function ($injector, $window) {
		var fn = {};

		fn.injectModule = function (name, base) {
			base = base ? base : name;
			var MESSAGE = 'Module ' + base + ' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.';
			var module;
			try {
				module = $injector.get(name);
			}
			catch (e) {
				console.error('ngquantum WARNING:', MESSAGE);
			}

			return module;
		}
		fn.isTouch = function () {
			return "createTouch" in $window.document && window.ontouchstart != null;
		}
		var isTouch = fn.isTouch();
		fn.isHtml = function (value) {
			return /<[a-z][\s\S]*>/i.test(value)
		}
		fn.ensureNumber = function (value, defaultval) {
			if (!value) return defaultval || 0;
			if (angular.isString(value)) {
				return parseFloat(value);
			}
			if (angular.isNumber(value)) {
				return value;
			}
			else return defaultval || 0;
		}
		fn.parseConstant = function (value) {
			if (/^(true|false|\d+|\-?[0-9]\d+)$/.test(value)) {
				return eval(value)
			}
			if (angular.isString(value)) {
				if (value[0] == '[' || (value[0] == '{' && value[1] !== '{{')) {
					try {
						return eval(value)
					}
					catch (e) {
						return value.trimStart("'").trimEnd("'")
					}
				}
				return value.trimStart("'").trimEnd("'")
			}

			return value;
		}
		fn.parseOptions = function (attr, options, prefix) {
			if (attr && angular.isDefined(attr.$$element)) {
				prefix = prefix || 'qo';
				angular.forEach(attr.$attr, function (value, key) {
					if (value.length && value.indexOf('qo-') > -1) {
						var oKey = fn.getOptionKey(key)

						options[oKey] = fn.parseConstant(attr[key]);
					}

				});
			}

			return options;
		}
		fn.observeOptions = function (attr, options, callback, prefix) {
			if (attr && angular.isDefined(attr.$$element)) {
				prefix = prefix || 'qo';
				if (attr.$$observers)
					for (var key in attr.$$observers) {
						if (key.length > 2 && key.startsWith(prefix)) {
							var oKey = fn.getOptionKey(key, prefix.length);
							attr.$observe(key, function (newValue, oldValue) {
								options[oKey] = fn.parseConstant(newValue);
								callback && callback(oKey);
							});

						};

					};
			}
			return options;
		}
		fn.id = function (prefix, random) {
			var id = prefix ? prefix : 'nq-', rd = random || 1000;
			return id + Math.floor((Math.random() * rd) + 1);
		}
		fn.getOptionKey = function (key, remove) {
			remove = remove || 2;
			if (key && key.length > remove) {
				var newKey = key.slice(remove);
				return newKey.charAt(0).toLowerCase() + newKey.slice(1);
			}
			return key
		}
		fn.formatUrl = function (url, params) {
			url = url.trimEnd('/')
			for (var o in params) {
				params[o] && (url += '/' + params[o]);
			}
			return url;
		}
		fn.getFieldValue = function (data, field) {
			if (field.indexOf('.') < 0)
				return data[field]
			else {
				var fields = field.split('.');
				var result = data;
				for (var i = 0; i < fields.length; i++) {
					if (result)
						result = result[fields[i]];
					else
						break;
				}
				return result;
			}
		}

		fn.bindTriggers = function (element, triggers, $master) {
			var array = triggers.split(' ');
			var hasclick = false;
			angular.forEach(array, function (trigger) {
				if (trigger === 'click') {
					element.on('click', $master.toggle);
					hasclick = true;

				}
				else if (trigger !== 'manual') {
					element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $master.enter);
					element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $master.leave);
					trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $master.$onFocusElementMouseDown);
				}
			});
			return hasclick;
		}
		fn.unBindTriggers = function (element, triggers, $master) {
			var array = triggers.split(' ');
			for (var i = array.length; i--;) {
				var trigger = array[i];
				if (trigger === 'click') {
					element.off('click keyup', $master.toggle);
				} else if (trigger !== 'manual') {
					element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $master.enter);
					element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $master.leave);
					trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $master.$onFocusElementMouseDown);
				}
			}
		}
		fn.stringParsers = [
			{
				re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
				parse: function (execResult) {
					return [
						execResult[1],
						execResult[2],
						execResult[3],
						execResult[4]
					];
				}
			},
			{
				re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
				parse: function (execResult) {
					return [
						2.55 * execResult[1],
						2.55 * execResult[2],
						2.55 * execResult[3],
						execResult[4]
					];
				}
			},
			{
				re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
				parse: function (execResult) {
					return [
						parseInt(execResult[1], 16),
						parseInt(execResult[2], 16),
						parseInt(execResult[3], 16)
					];
				}
			},
			{
				re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
				parse: function (execResult) {
					return [
						parseInt(execResult[1] + execResult[1], 16),
						parseInt(execResult[2] + execResult[2], 16),
						parseInt(execResult[3] + execResult[3], 16)
					];
				}
			}
		]
		fn.docHeight = function () {
			var body = document.body,
				html = document.documentElement;

			var height = Math.max(body.scrollHeight, body.offsetHeight,
				html.clientHeight, html.scrollHeight, html.offsetHeight);
			return height;
		}
		return fn;
	}
	])
'use strict';
angular.module('ngQuantum.services.lazy', [])
	.provider('$lazyRequest', function () {
		var timeout = this.timeout = 2000;
		this.$get = ['$timeout', '$rootScope', '$http',
			function ($timeout, $rootScope, $http) {
				function Factory(fn, time) {
					time = time || 0;
					if (!$rootScope.$$phase) {
						$rootScope.$apply(function () {
							$rootScope.$pendingRequestCount = $rootScope.$pendingRequestCount || 0;
							$rootScope.$pendingRequestCount++;
						})
					}
					else {
						$rootScope.$pendingRequestCount = $rootScope.$pendingRequestCount || 0;
						$rootScope.$pendingRequestCount++;
					}
					return $timeout(function () {
						var promise = fn();
						if (promise && angular.isDefined(promise.then))
							promise.then(function () {
								$rootScope.$pendingRequestCount > 0 && $rootScope.$pendingRequestCount--;
							})
						return promise;
					}, time);
				}

				return Factory;
			}
		];
	});
'use strict';
angular.module('ngQuantum.services.mouse', [])
	.provider('$mouseConfig', function () {
		this.adjustOldDeltas = true, // see shouldAdjustOldDeltas() below
			this.normalizeOffset = true  // calls getBoundingClientRect for each event
		this.$get = function () {
			return this;
		};
	})
	.factory('$mouse', ['$injector', '$window', '$mouseConfig', function ($injector, $window, $mouseConfig) {
		var isTouch = "createTouch" in $window.document && window.ontouchstart != null;
		var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
			toBind = ('onwheel' in document || document.documentMode >= 9) ?
				'wheel' : 'mousewheel DomMouseScroll, MozMousePixelScroll',
			slice = Array.prototype.slice,
			nullLowestDeltaTimeout, lowestDelta;
		var mause = {};


		mause.relativeX = function (event, container) {
			if (event.target == container[0] && event.offsetX) {
				return event.offsetX
			}
			else {
				var clinetX = event.pageX || event.clientX || (typeof (event.originalEvent) != 'undefined' ? event.originalEvent.touches[0].clientX : event.touches[0].clientX);
				return clinetX - container.offset().left;
			}
		}
		mause.relativeY = function (event, container) {
			if (event.target == container[0] && event.offsetY) {
				return event.offsetY
			}
			else {
				var clinetY = event.pageY || event.clientY || (typeof (event.originalEvent) != 'undefined' ? event.originalEvent.touches[0].clientY : event.touches[0].clientY);
				return clinetY - container.offset().top;
			}
		}
		mause.relativePos = function (event, container) {
			return {
				top: mause.relativeY(event, container),
				left: mause.relativeX(event, container)
			}
		}
		mause.down = function (element, callback) {
			var eventName = isTouch ? 'touchstart' : 'mousedown';
			return element.on(eventName, callback);
		}
		mause.move = function (element, callback, event) {
			var eventName = ((event && event.touches) || isTouch) ? 'touchmove' : 'mousemove';
			return element.on(eventName, callback);
		}
		mause.up = function (element, callback, event) {
			var eventName = ((event && event.touches) || isTouch) ? 'touchend' : 'mouseup';
			return element.on(eventName, callback);
		}

		mause.offDown = function (element, callback) {
			var eventName = isTouch ? 'touchstart' : 'mousedown';
			return callback ? element.off(eventName, callback) : element.off(eventName);
		}
		mause.offMove = function (element, callback) {
			var eventName = isTouch ? 'touchmove' : 'mousemove';
			return callback ? element.off(eventName, callback) : element.off(eventName);
		}
		mause.offUp = function (element, callback) {
			var eventName = isTouch ? 'touchend' : 'mouseup';
			return callback ? element.off(eventName, callback) : element.off(eventName);
		}
		mause.offEnter = function (element, callback) {
			var eventName = isTouch ? 'touchstart' : 'mouseenter';
			return callback ? element.off(eventName, callback) : element.off(eventName);
		}

		mause.onWheel = function (element, callback) {
			if (isTouch)
				return false;
			element.on(toBind, function (event) {
				element.data('mousewheel-line-height', getLineHeight(element));
				element.data('mousewheel-page-height', element.height());

				return wheelHandler(element, event, callback)
			})
		}
		mause.offWheel = function (element, callback) {
			if (isTouch)
				return false;
			element.data('mousewheel-line-height', '');
			element.data('mousewheel-page-height', '');
			return callback ? element.off(toBind, callback) : element.off(toBind);
		}
		function wheelHandler(element, orgEvent, callback) {
			var orgEvent = orgEvent || window.event,
				args = [].slice.call(arguments, 1),
				delta = 0,
				deltaX = 0,
				deltaY = 0,
				absDelta = 0,
				offsetX = 0,
				offsetY = 0;
			var event = angular.extend({}, orgEvent);
			event.type = 'mousewheel';

			event.preventDefault = function () {
				if (orgEvent.preventDefault) {
					orgEvent.preventDefault();
				} else {
					orgEvent.returnValue = false;
				}
			};
			event.stopPropagation = function () {
				if (orgEvent.stopPropagation) {
					orgEvent.stopPropagation();
				} else {
					orgEvent.cancelBubble = false;;
				}
			};
			if ('detail' in orgEvent) { deltaY = orgEvent.detail * -1; }
			if ('wheelDelta' in orgEvent) { deltaY = orgEvent.wheelDelta; }
			if ('wheelDeltaY' in orgEvent) { deltaY = orgEvent.wheelDeltaY; }
			if ('wheelDeltaX' in orgEvent) { deltaX = orgEvent.wheelDeltaX * -1; }
			if ('axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
				deltaX = deltaY * -1;
				deltaY = 0;
			}
			delta = deltaY === 0 ? deltaX : deltaY;
			if ('deltaY' in orgEvent) {
				deltaY = orgEvent.deltaY * -1;
				delta = deltaY;
			}
			if ('deltaX' in orgEvent) {
				deltaX = orgEvent.deltaX;
				if (deltaY === 0) { delta = deltaX * -1; }
			}
			if (deltaY === 0 && deltaX === 0) { return; }
			if (orgEvent.deltaMode === 1) {
				var lineHeight = element.data()['mousewheel-line-height'];
				delta *= lineHeight;
				deltaY *= lineHeight;
				deltaX *= lineHeight;
			} else if (orgEvent.deltaMode === 2) {
				var pageHeight = element.data()['mousewheel-page-height'];
				delta *= pageHeight;
				deltaY *= pageHeight;
				deltaX *= pageHeight;
			}
			absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));

			if (!lowestDelta || absDelta < lowestDelta) {
				lowestDelta = absDelta;
				if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
					lowestDelta /= 40;
				}
			}
			if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
				delta /= 40;
				deltaX /= 40;
				deltaY /= 40;
			}
			delta = Math[delta >= 1 ? 'floor' : 'ceil'](delta / lowestDelta);
			deltaX = Math[deltaX >= 1 ? 'floor' : 'ceil'](deltaX / lowestDelta);
			deltaY = Math[deltaY >= 1 ? 'floor' : 'ceil'](deltaY / lowestDelta);
			if ($mouseConfig.normalizeOffset && element[0].getBoundingClientRect) {
				var boundingRect = element[0].getBoundingClientRect();
				offsetX = event.clientX - boundingRect.left;
				offsetY = event.clientY - boundingRect.top;
			}
			event.deltaX = deltaX;
			event.deltaY = deltaY;
			event.deltaFactor = lowestDelta;
			event.offsetX = offsetX;
			event.offsetY = offsetY;
			event.deltaMode = 0;
			args.unshift(event, delta, deltaX, deltaY);
			if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
			nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
			return callback(event);
		}
		function shouldAdjustOldDeltas(orgEvent, absDelta) {
			return $mouseConfig.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
		}
		function nullLowestDelta() {
			lowestDelta = null;
		}
		function getLineHeight(elem) {
			var $parent = elem.offsetParent ? elem.offsetParent() : elem.parent();
			if (!$parent.length) {
				$parent = angular.element('body');
			}
			return parseInt($parent.css('fontSize'), 10) || parseInt(elem.css('fontSize'), 10) || 16;
		}
		return mause;
	}])
'use strict';
angular.module('ngQuantum.services.parseOptions', [])
	.provider('$parseOptions', function () {
		var defaults = this.defaults = { regexp: /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/ };
		this.$get = [
			'$parse',
			'$q',
			function ($parse, $q) {
				function ParseOptionsFactory(attr, $element) {
					var $parseOptions = {};
					var options = angular.extend({}, defaults);
					$parseOptions.$values = [];
					var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;
					$parseOptions.init = function () {
						$parseOptions.$match = match = attr.match(options.regexp);
						displayFn = $parse(match[2] || match[1]), valueName = match[4] || match[6], keyName = match[5], groupByFn = $parse(match[3] || ''), valueFn = $parse(match[2] ? match[1] : valueName), valuesFn = $parse(match[7]);

					};
					$parseOptions.valuesFn = function (scope, controller) {
						return $q.when(valuesFn(scope, controller)).then(function (values) {
							$parseOptions.$values = values ? parseValues(values) : {};
							return $parseOptions.$values;
						});
					};
					$parseOptions.parseInit = function () {

						$parseOptions.$values = parseElement($element)
					}
					$parseOptions.valuesParse = function (elem) {
						return $q.when(elem).then(function (el) {
							$parseOptions.$values = parseElement(el) || [];
							return $parseOptions.$values;
						});
					};
					function parseValues(values) {
						return values.map(function (match, index) {
							var locals = {}, label, value, group;
							locals[valueName] = match;
							label = displayFn(locals);
							value = valueFn(locals) || label;
							group = groupByFn(locals);
							return {
								label: label,
								value: value,
								group: group ? { label: group } : undefined,
								disabled: match.disabled
							};
						});
					}

					function parseElement(element) {
						var array = [];

						angular.forEach(element.children(), function (value, key) {
							if (angular.element(value).is("option")) {
								array.push(optionToData(angular.element(value)))
							}
							else if (angular.element(value).is("optgroup")) {
								var group = optionGroupToData(angular.element(value));
								angular.forEach(angular.element(value).children(), function (gval, gkey) {
									array.push(optionToData(angular.element(gval), group))
								})

							}


						})
						return array;
					}

					function optionToData(element, group) {
						return {
							value: element.prop("value"),
							label: element.text(),
							group: group,
							disabled: element.prop("disabled") || group && group.disabled
						};
					}

					function optionGroupToData(element) {
						return {
							label: element.attr("label"),
							disabled: element.prop("disabled")
						};
					}

					if ($element)
						$parseOptions.parseInit();
					else
						$parseOptions.init();
					return $parseOptions;
				}
				return ParseOptionsFactory;
			}
		];
	});
'use strict';
angular.module('ngQuantum.services.placement', ['ngQuantum.services.helpers'])
	.factory('$placement', ['$helpers', function ($helpers) {
		var fn = {};
		fn.applyPlacement = function (element, $target, options) {
			if (!element || !$target)
				return;
			var placement = options.placement,
				position = getPosition(element, options);

			options.originalPlacement = placement
			var autoToken = /\s?auto?\s?/i
			var autoPlace = autoToken.test(placement)
			if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

			if (autoPlace) {
				placement = getPlacement(element, placement, position, options.container)
				$target.removeClass(options.originalPlacement).addClass(placement)
			}
			var width = $target.outerWidth(true),
				height = $target.outerHeight(true);
			var offset = getCalculatedOffset(placement, position, width, height);

			offset.top = offset.top + $helpers.ensureNumber(options.offsetTop)
			offset.left = offset.left + $helpers.ensureNumber(options.offsetLeft)
			var marginTop = parseInt($target.css('margin-top'), 10)
			var marginLeft = parseInt($target.css('margin-left'), 10)
			if (isNaN(marginTop)) marginTop = 0;
			if (isNaN(marginLeft)) marginLeft = 0;

			offset.top = offset.top + marginTop;
			offset.left = offset.left + marginLeft;

			if (options.insideFixed) {
				$target.css(offset);
			} else
				$target.offset(offset);
			fn.ensurePosition($target, element, options)
			return options;
		}
		fn.verticalPlacement = function ($target, options) {
			var windowHeght = window.screen.height || 0;
			var targetHeight = $target.height() || 0;
			var diff = windowHeght - targetHeight - 10;
			if (diff > 0) {
				var top = 0;
				switch (options.placement) {
					case 'center':
						top = diff / 2
						break;
					case 'bottom':
						top = diff
						break;
					case 'near-top':
						top = diff / 3
						break;
					case 'near-bottom':
						top = (diff / 3) * 2
						break;
					default:
						top = 0
				}
				$target.css('top', top);
			}

		}
		fn.ensurePosition = function ($target, element, options) {
			var offset = options.insideFixed ? $target.position() : $target.offset(), ww = window.screen.width, dh = $helpers.docHeight(),
				tw = $target.width(), th = $target.height(), eh = element.height(), eo = options.insideFixed ? element.position() : element.offset(), classList = $target.attr('class');
			if (offset.left < 0) {
				$target.css('left', 0);
				$target.attr('class', classList.replace('right', 'left'));
			}
			else if (offset.left > (ww - tw)) {
				$target.css('left', (element.width() - tw));
				$target.attr('class', classList.replace('left', 'right'));
			}
			if (offset.top < 0) {
				$target.css('top', eo.top);
				$target.attr('class', classList.replace('bottom', 'top'));
			}
			else if (offset.top > (dh - th)) {
				$target.css('left', (eo.top - th));
				$target.attr('class', classList.replace('top', 'bottom'));
			}


		}
		fn.replaceArrow = function ($target, delta, dimension, position) {
			$target.find('.arrow').css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
		}
		function getPosition(element, options) {
			var el = element[0];
			var clipRect = (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
				width: el.offsetWidth
				, height: el.offsetHeight
			};
			var rectObj = {};
			for (var o in clipRect) {
				rectObj[o] = clipRect[o];
			}
			var offset = options.insideFixed ? element.position() : element.offset();
			var result = angular.extend({}, rectObj, offset);
			return result;
		}
		function getCalculatedOffset(placement, position, actualWidth, actualHeight) {
			var offset;
			var split = placement.split('-');
			switch (split[0]) {
				case 'right':
					offset = {
						top: position.top + (position.height / 2) - (actualHeight / 2),
						left: position.left + position.width
					};
					break;
				case 'bottom':
					offset = {
						top: position.top + position.height,
						left: position.left + (position.width / 2) - (actualWidth / 2)
					};
					break;
				case 'left':
					offset = {
						top: position.top + (position.height / 2) - (actualHeight / 2),
						left: position.left - actualWidth
					};
					break;
				default:

					offset = {
						top: position.top - actualHeight,
						left: position.left + (position.width / 2) - (actualWidth / 2)
					};
					break;
			}
			if (!split[1]) {
				return offset;
			}
			if (split[0] === 'top' || split[0] === 'bottom') {
				switch (split[1]) {
					case 'left':
						offset.left = position.left;
						break;
					case 'right':
						offset.left = position.left + position.width - actualWidth;
				}
			} else if (split[0] === 'left' || split[0] === 'right') {
				switch (split[1]) {
					case 'top':
						offset.top = position.top - actualHeight + position.height;
						break;
					case 'bottom':
						offset.top = position.top
				}
			}
			return offset;
		}
		function getPlacement(element, placement, position, container) {
			var actualWidth = element[0].offsetWidth
			var actualHeight = element[0].offsetHeight
			var $parent = element.parent()
			if (container)
				container == container == 'body' ? window : angular.element(container)[0];
			var docScroll = document.documentElement.scrollTop || document.body.scrollTop
			var parentWidth = container ? container.innerWidth : $parent.outerWidth()
			var parentHeight = container ? container.innerHeight : $parent.outerHeight()
			var parentLeft = container ? 0 : $parent.offset().left

			placement = placement == 'bottom' && position.top + position.height + actualHeight - docScroll > parentHeight ? 'top' :
				placement == 'top' && position.top - docScroll - actualHeight < 0 ? 'bottom' :
					placement == 'right' && position.right + actualWidth > parentWidth ? 'left' :
						placement == 'left' && position.left - actualWidth < parentLeft ? 'right' :
							placement
			return placement;
		}

		return fn;
	}
	]);

+function (window, angular, undefined) {
	'use strict';
	angular.module('ngQuantum.services', [
		'ngQuantum.services.lazy',
		'ngQuantum.services.mouse',
		'ngQuantum.services.helpers',
		'ngQuantum.services.parseOptions',
		'ngQuantum.services.templateHelper',
		'ngQuantum.services.placement',
		'ngQuantum.services.color'
	])

}(window, window.angular);
'use strict';
angular.module('ngQuantum.services.templateHelper', []).factory('templateHelper', [
	'$http',
	'$q',
	'$templateCache',
	'$timeout',
	function ($http, $q, $templateCache, $timeout) {
		var fn = {};
		fn.fetchTemplate = function (template) {
			return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) {
				if (angular.isObject(res)) {
					return res.data;
				}
				return res;
			});
		}
		fn.fetchContentTemplate = function ($object) {
			return $object.$promise.then(function (template) {
				var tm = angular.element(template);
				var tel = tm.find('[ng-bind="content"], [ng-bind-html="content"]');
				var ct = $object.$options.contentTemplate;
				if ((angular.isString(ct) && ct.indexOf('.html') > -1)) {
					return fn.fetchTemplate($object.$options.contentTemplate).then(function (contentTemplate) {
						if (tel.length) {
							tel.removeAttr('ng-bind').removeAttr('ng-bind-html').html(contentTemplate)
							return tm;
						}
						else
							return contentTemplate
					});
				}
				return template;

			});
		}
		fn.fetchContent = function ($object) {
			return $q.when($object).then(function (template) {
				return template;
			});
		}
		return fn;
	}
]);
+function () {
	'use strict';
	angular.module('ngQuantum.alert', ['ngQuantum.popMaster', 'ngQuantum.services.helpers'])
		.run(['$templateCache', function ($templateCache) {
			'use strict';
			$templateCache.put('alert/alert.tpl.html',
				"<div class=\"alert alert-dismissable\" tabindex=\"-1\" ng-class=\"alertType\"><div class=\"alert-inner\"><div class=\"alert-bg\" ng-class=\"alertType\"></div><a role=\"button\" tabindex=\"0\" class=\"close\" ng-click=\"$hide()\"><i ng-class=\"$closeIcon\"></i></a> <strong class=\"alert-title\" ng-if=\"title\" ng-bind=\"title\"></strong><span  ng-if=\"title\" ng-bind-html=\"content\"></span><div ng-if=\"!title\" ng-bind-html=\"content\"></div></div></div>"
			);

		}])
		.provider('$alert', function () {
			var defaults = this.defaults = {
				effect: 'fade-in',
				typeClass: 'alert',
				prefixEvent: 'alert',
				placement: 'top-right',
				fireEmit: true,
				template: 'alert/alert.tpl.html',
				container: false,
				directive: 'nqAlert',
				instanceName: 'alert',
				backdrop: false, //NOT USED
				displayReflow: true,
				clearExists: false,
				keyboard: true,
				trigger: 'click',
				show: true,
				html: true,
				independent: true,
				preventReplace: true,
				alertType: 'info',
				duration: 3000,
				autoDestroy: false,
				onHide: false,
				closeIcon: 'fic fu-cross'
			};
			this.$get = ['$timeout', '$rootScope', '$popMaster', '$compile', '$helpers', '$sce', '$parse',
				function ($timeout, $rootScope, $popMaster, $compile, $helpers, $sce, $parse) {
					function AlertFactory(config, title, alertType, placement) {
						var $alert = {}, attr;
						if (angular.isString(config)) {
							config = {
								content: config,
								title: title,
								alertType: alertType || defaults.alertType,
								placement: placement || defaults.placement
							}
						}
						if (!config.$scope) {
							config.autoDestroy = true;
						}
						angular.isObject(title) && (attr = title)
						attr && (config = $helpers.parseOptions(attr, config))
						var options = angular.extend({}, defaults, config);
						if (options.containerSelf)
							options.container = options.containerSelf;
						var container
						if (!options.container)
							getContainer();
						$alert = $popMaster(null, options);
						var scope = $alert.$scope;
						if (attr)
							options = $alert.$options = $helpers.observeOptions(attr, $alert.$options);
						else {
							options.content && (scope.content = options.content)
							options.title && (scope.title = options.title)

						}
						if (attr && attr.onHide)
							options.onHide = $parse(attr.onHide);
						var show = $alert.show;
						$alert.show = function () {
							scope.$closeIcon = options.closeIcon;
							options.alertType && (scope.alertType = 'alert-' + options.alertType)
							container && container.show()
							var promise = show();
							$compile($alert.$target)(scope);
							if (options.duration)
								$timeout(function () {
									$alert && $alert.hide();
								}, $helpers.ensureNumber(options.duration, 3000));
							return promise;
						};
						var hide = $alert.hide;
						$alert.hide = function () {
							var promise = hide();
							promise && promise.then(function () {
								options.onHide && options.onHide(scope);
								if (container) {
									var chlids = container.children();
									if (!chlids || chlids.length < 1) {
										container.hide();
									}
								}
								options.autoDestroy && $alert && $alert.destroy();
							})
							return promise;
						};
						function getContainer() {
							var placement = '';
							options.placement && (placement = '.' + options.placement)
							container = angular.element('body').find('.alert-container' + placement);
							if (!container || container.length < 1) {
								container = angular.element('<div class="alert-container ' + options.placement + '"></div>');
								container.prependTo('body')
							}
							options.container = container;
						}

						if (attr) {
							angular.forEach(['title', 'content'], function (key) {
								var akey = 'qs' + key.capitaliseFirstLetter();
								attr[akey] && (scope[key] = $sce.trustAsHtml(attr[akey]));
								attr.$$observers && attr.$$observers[akey] && attr.$observe(akey, function (newValue, oldValue) {
									scope[key] = $sce.trustAsHtml(newValue);
								});
							});
							if (attr && angular.isDefined(options.directive)) {
								attr[options.directive] && options.$scope.$watch(attr[options.directive], function (newValue, oldValue) {
									if (angular.isObject(newValue)) {
										angular.extend(scope, newValue);
									} else {
										scope.content = newValue;
									}
								}, true);
							}
						}
						scope.$on('$destroy', function () {
							$alert && !$alert.isDestroyed && $alert.destroy();
							$alert = null;
						});
						return $alert;
					}
					return AlertFactory;
				}
			];
		})
		.directive("nqAlert", ['$alert',
			function ($alert) {
				return {
					restrict: 'EAC',
					scope: true,
					link: function postLink(scope, element, attr, transclusion) {
						var firstLoad;
						var options = {
							$scope: scope
						};
						options.uniqueId = attr.qoUniqueId || attr.id || options.$scope.$id;
						!angular.isDefined(attr.qsContent) && (scope.content = element.html(), element.html(''))
						if (angular.isDefined(attr.qoContainer) && attr.qoContainer == 'self') {
							options.containerSelf = element;
						}
						!attr.qoShow && (options.show = false);

						var alert = $alert(options, attr);
						if (angular.isDefined(attr.qsShowOn)) {
							scope.$watch(attr.qsShowOn, function (value) {
								(firstLoad || value) && alert.toggle();
								firstLoad = true;
							})
						}
						if (!angular.isDefined(attr.qoContainer) || !attr.qoContainer == 'self') {
							element.on('click', function () {
								alert.toggle();
							})
						}

					}
				};
			}]);
}();
(function (window, angular, undefined) {
	'use strict';
	var asideoptions = {
		effect: 'slide-left',
		speed: 'fastest',
		side: 'left',
		opened: false,
		pinned: false,
		collapsed: false,
		collapsible: false,
		pinnable: false,
		pinnedScreenSize: 1300,
		collapsedScreenSize: 991,
		closedScreenSize: 767,
		position: 'fixed',   // can be fixed|relative|absolute
		offCanvas: 'mobile', // can be all|desktop|touches or false,
		offCanvasBody: 'body',
		container: 'self',
		theme: false,
		backDrop: false,
		topOffset: 50,
		scrollOffsetTop: false, //if you navbar is fixed set this false
		bottomOffset: 0,
		width: false,
		enlargeHover: false, //ngSwipeLeft and ngSwipeRight can be used for touch devices
	};
	angular.module('ngQuantum.aside', ['ngQuantum.services.helpers'])
		.provider('$aside', function () {
			var defaults = this.defaults = asideoptions;

			this.$get = ['$rootScope', '$animate', '$timeout', '$window',
				function ($rootScope, $animate, $timeout, $window) {
					var isTouch = "createTouch" in $window.document && window.ontouchstart != null;
					function Factory(element, config, attr) {
						var $aside = {}
						var options = $aside.$options = angular.extend({}, defaults, config);
						var scope = options.$scope || $rootScope.$new();
						var body = angular.element(options.offCanvasBody), $container, applyBody = options.pinnable || options.collapsible;
						var classes = ['aside-pinned', 'aside-collapsed', 'aside-opened', 'aside-closed'], backDrop;


						if (attr && attr.$$observers) {
							angular.forEach(attr.$$observers, function (value, key) {
								if (angular.isDefined(options[key])) {
									attr.$observe(key, function (newValue, oldValue) {
										if (newValue != options[key]) {
											changeOptions(key, newValue)
											options[key] = newValue;
										}

									});
								}

							});
						}

						$aside.toggle = function () {
							if ($aside.$isOpen) {
								$aside.close()
							}
							else {
								$aside.open()
							}
							scope.$$phase || scope.$digest();
						};
						$aside.toggleCollapse = function (collapse) {
							if (!options.collapsible)
								return;
							if ($aside.$collapsed) {
								if (collapse)
									return;
								element.removeClass('aside-collapsed');
								applyBody && body.removeClass(options.side + '-aside-collapsed');
								$timeout(function () {
									$aside.$collapsed = false;
								}, 0)

								if (options.enlargeHover && !isTouch) {
									element.off('mouseenter mouseleave')
									$aside.$isOpen && element.on('mouseleave', function () {
										$aside.toggleCollapse();
									})
								}
							}
							else {
								if (!$aside.$isOpen || collapse == false)
									return;
								if (options.enlargeHover && !isTouch) {
									element.off('mouseenter mouseleave')
									element.on('mouseenter', function () {
										$aside.toggleCollapse();
									})
								}
								element.addClass('aside-collapsed');
								applyBody && body.addClass(options.side + '-aside-collapsed');
								$timeout(function () {
									$aside.$collapsed = true;
								}, 0)

							}
						};
						$aside.close = function () {
							if ($aside.$isOpen == false)
								return;

							if (options.effect) {
								element.off('mouseenter mouseleave')
								element.removeClass('aside-opened');
								element.show();
								element.addClass(options.speed);
								$animate.removeClass(element, options.effect).then(function () {
									element.hide();
									element.addClass('aside-closed');
									element.removeClass(options.speed);
									element.removeClass('ng-animate');
								})
							} else {
								element.removeClass('aside-opened');
								element.addClass('aside-closed');
								element.removeClass(options.speed);
								element.removeClass(options.effect);
							}
							clearStyle();
							$timeout(function () {
								$aside.$isOpen = false;
							}, 0)

							backDrop && backDrop.detach();
						};
						$aside.open = function () {
							if ($aside.$isOpen)
								return;
							clearStyle();
							element.removeClass('aside-closed');
							$container && $container.append(element);
							if (options.effect) {
								element.show();
								element.addClass(options.speed);
								element.animationEnd(function () {
									element.removeClass(options.speed);
									element.removeClass('ng-animate');
								});
								$animate.addClass(element, options.effect);
								element.addClass('aside-opened');

							} else
								element.addClass('aside-opened');
							applyBody && body.addClass(options.side + '-aside-opened');

							$aside.$isOpen = true;
							$aside.togglePin($aside.$pinned || false)
							$aside.toggleCollapse($aside.$collapsed || false);
							backDrop && element.after(backDrop);
							$timeout(function () {
								$aside.$collapsed = false;
								$aside.$isOpen = true;
							}, 0)
						};
						$aside.togglePin = function (pin) {
							if (!options.pinnable)
								return;
							if ($aside.$pinned) {
								if (pin) {
									if (!$aside.$isOpen) {
										$aside.open()
										return;
									}
									element.addClass('aside-pinned');
									applyBody && body.addClass(options.side + '-aside-pinned');
									$aside.$pinned = true;
									return;
								};
								element.removeClass('aside-pinned');
								applyBody && body.removeClass(options.side + '-aside-pinned');
								$aside.$pinned = false;
							}
							else {
								if (!$aside.$isOpen || pin == false)
									return;
								element.addClass('aside-pinned');
								applyBody && body.addClass(options.side + '-aside-pinned');
								$aside.$pinned = true;
							}
							if (!options.enlargeHover || options.enlargeHover == 'false')
								element.off('mouseenter mouseleave');
							else {
								element.off('mouseenter mouseleave')
                                element.on('mouseleave', function () {
                                    if (!$aside.$pinned)
									    $aside.toggleCollapse();
								})
							}
						};
						function refresh() {
							element.addClass('aside')
							clearStyle();
							if (!options.opened) {
								$aside.close();
							} else {
								$aside.open();
								options.pinned && $aside.togglePin(true)
								options.collapsed && $aside.toggleCollapse(true);
							}
							applyOptions();
							addBackdrop();
							addToContainer();
							clearTheme(options.theme)
							clearPosition(options.position)
							clearOffCanvas(options.offCanvas)
							checkSizes();
						};
						window.addResizeEvent(function () {
							$timeout(function () {
								var newVal = $window.innerWidth;
								checkSizes(newVal);
							}, 0)
						})
						function clearStyle() {
							applyBody && body.removeClasses([options.side + '-aside-opened', options.side + '-aside-collapsed', options.side + '-aside-pinned']);
							element && element.removeClasses(classes);
						}
						function checkSizes(newVal) {
							newVal = newVal || $window.innerWidth;
							if (newVal == $aside.windowWidth)
								return;
							if (options.closedScreenSize && options.closedScreenSize >= newVal) {
								$aside.close();
							} else {
								if (options.collapsedScreenSize && options.collapsedScreenSize >= newVal) {
									$aside.toggleCollapse(true);
								}
								/*if (options.pinnedScreenSize && options.pinnedScreenSize <= newVal) {
									$aside.togglePin(true);
								}*/
							}
							$aside.windowWidth = newVal;
						}
						function addBackdrop() {
							if (backDrop) {
								backDrop.off();
								backDrop.remove();
							}
							if (!options.backDrop)
								return;
							backDrop = angular.element('<div class="aside-overlay"></div>')
								.on('click', function () {
									$aside ? $aside.close() : backDrop.remove();
								});
						}
						function changeOptions(key, value) {
							switch (key) {
								case "theme":
									clearTheme(value)
									break;
								case "position":
									clearPosition(value)
									break;
								case "offCanvas":
									clearOffCanvas(value)
									break;
								case "topOffset":
									element.css('top', value);
									break;
								case "bottomOffset":
									element.css('bottom', value);
									break;
								case "backDrop":
									addBackdrop();
									break;
								case "side":
									$aside.close();
									$aside.open();
									break;
							}

						}
						function applyOptions() {
							element.addClass('aside-' + options.side);
							element.css('top', options.topOffset && options.topOffset || 0);
							element.css('bottom', options.bottomOffset && options.bottomOffset || 0);
							if (options.width)
								element.css('width', options.width);
							if (options.collapsible)
								applyBody && body.addClass(options.side + '-aside-collapsible');
						}
						function addToContainer() {
							if (options.container && options.container !== 'self') {
								var cont = angular.element(options.container);
								if (cont.length) {
									$container = angular.element(cont[0]);
									$container.append(element);
								}
							}
						}
						function clearPosition(value) {
							if (options.position) {
								element.removeClass('aside-' + options.position)
								applyBody && body.removeClass(options.side + '-aside-' + options.position)
							}
							if (value) {
								element.addClass('aside-' + value)
								applyBody && body.addClass(options.side + '-aside-' + value)
							}
						}
						function clearOffCanvas(value) {
							if (options.offCanvas) {
								element.removeClass('off-canvas-' + options.offCanvas)
								applyBody && body.removeClass(options.side + '-off-canvas-' + options.offCanvas)
							}
							if (value) {
								element.addClass('off-canvas-' + value)
								applyBody && body.addClass(options.side + '-off-canvas-' + value)
							}
						}
						function clearTheme(value) {
							options.theme && element.removeClass('aside-' + options.theme)
							value && element.addClass('aside-' + value);
						}
						refresh();
						scope.$$postDigest(function () {
							scope.$aside = $aside
						});
						angular.element(window).on('scroll', function (evt) {
							if (options.scrollOffsetTop && options.topOffset > 0) {
								var top = angular.element(window).scrollTop()
								if (top > options.topOffset)
									element.css('top', 0)
								else if (top == 0)
									element.css('top', options.topOffset)
								else
									element.css('top', options.topOffset - top)
							}

						})
						scope.$on('$destroy', function () {
							if (backDrop) {
								backDrop.off();
								backDrop.remove();
							}
							$aside && ($aside == null);
							element && element.off();
							clearStyle();
						});
						angular.element(document).ready(function () {
							setTimeout(function () {
								if (element.height() > window.innerHeight) {
									element.css('position', 'relative')
									setTimeout(function () {
										element.css('position', '')
									}, 100)
								}

							}, 10)
						})
						return $aside;
					}
					return Factory;
				}
			];
		})
		.directive("nqAside", ["$aside", '$helpers', function ($aside, $helpers) {
			return {
				restrict: "AC",
				scope: true,
				link: function postLink(scope, element, attr, controller) {
					var options = {
						$scope: scope,
						id: attr.id || 'aside-' + scope.$id
					}
					angular.forEach(asideoptions, function (val, key) {
						if (angular.isDefined(attr[key]) && attr[key].indexOf('{{') < 0)
							options[key] = $helpers.parseConstant(attr[key]);

					});
					var header = element.find('.aside-header');
					if (header.length) {
						var hh = header.outerHeight(true);
						element.css('padding-top', hh), header.css('margin-top', -hh)
					}
					var footer = element.find('.aside-footer')
					if (footer.length) {
						var fh = footer.outerHeight(true);
						element.css('padding-bottom', fh);
					}
					var aside = new $aside(element, options, attr);
					var asideName = attr.nqAside;
					if (asideName)
						scope.$parent[asideName] = aside;
				}
			};
		}])
		.directive('asideToggle', ['$timeout', function ($timeout) {
			return {
				restrict: 'A',
				link: function postLink(scope, element, attr) {
					element.on('click', function () {
						var asideEl = attr.asideToggle ? angular.element(attr.asideToggle) : false;
						if (asideEl.length) {
							var aScope = asideEl.scope();
							if (aScope && aScope.$aside) {
								$timeout(function () {
									aScope.$aside.toggle();
								}, 0);
							}


						}

					})
				}
			};
		}])
})(window, window.angular);
+function (window, angular, undefined) {
	'use strict';
	var nqButtonsApp = angular.module('ngQuantum.button', ['ngAnimate', 'ngQuantum.services.helpers'])
		.provider('$button', function () {
			var defaults = this.defaults = {
				activeClass: 'active',
				toggleEvent: 'click',
				activeIcon: '',
			};
			this.$get = function () {
				return { defaults: defaults };
			};
		});
	angular.forEach(['CheckboxGroup', 'RadioGroup'], function (directive) {
		nqButtonsApp.directive('nq' + directive, function () {
			return {
				restrict: 'A',
				require: 'ngModel',
				compile: function postLink(element, attr) {
					var dirType = directive == 'CheckboxGroup' ? 'checkbox' : 'radio'
					element.attr('data-toggle', 'buttons');
					element.removeAttr('ng-model');
					var children = element.find('input[type="' + dirType + '"]');
					var trueVal, falseVal
					if (dirType == 'checkbox')
						trueVal = attr.trueValue, falseVal = attr.falseValue;

					angular.forEach(children, function (child) {
						var childEl = angular.element(child);
						childEl.attr('nq-' + dirType + '-button', '');
						if (dirType == 'checkbox') {
							childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));
							(!childEl.attr('ng-true-value') && trueVal) && childEl.attr('ng-true-value', trueVal);
							(!childEl.attr('ng-false-value') && falseVal) && childEl.attr('ng-false-value', falseVal)
						}
						else
							childEl.attr('ng-model', attr.ngModel);
						childEl.attr('name', attr.ngModel);
						attr.showTick && childEl.attr('show-tick', attr.showTick)
						if (attr.ngChange) {
							if (angular.isDefined(childEl.attr('ng-change'))) {
								childEl.attr('ng-change', childEl.attr('ng-change') + ';' + attr.ngChange);
							}
							else
								childEl.attr('ng-change', attr.ngChange);
						}

					});
				}
			};
		});
	})
	angular.forEach(['Checkbox', 'Radio', 'Toggle'], function (directive) {
		nqButtonsApp.directive('nq' + directive + 'Button', ['$button', '$helpers', function ($button, $helpers) {
			return {
				restrict: 'A',
				require: 'ngModel',
				link: function postLink(scope, element, attr, controller) {
					var options = $button.defaults;
					directive = directive.toLowerCase();
					directive == 'toggle' && (directive = 'checkbox')
					var isInput = attr.type === directive;
					var activeElement = isInput ? element.parent() : element;
					var trueValue, falseValue;
					if (directive == 'checkbox') {
						trueValue = angular.isDefined(attr.ngTrueValue) ? $helpers.parseConstant(attr.ngTrueValue) : true;
						falseValue = angular.isDefined(attr.ngFalseValue) ? $helpers.parseConstant(attr.ngFalseValue) : false;
					}
					else {
						trueValue = attr.ngValue ? scope.$eval(attr.ngValue) : $helpers.parseConstant(attr.value);
					}

					if ($helpers.parseConstant(attr.showTick) == true) {
						activeElement.addClass('tick-right')
					}
					attr.showTick == 'left' && activeElement.addClass('tick-left')
					angular.isDefined(attr.checked) && controller.$setViewValue(trueValue);

					scope.$watch(attr.ngModel, function (newValue, oldValue) {
						var isActive = angular.equals($helpers.parseConstant(controller.$modelValue), trueValue);
						!isActive && element.removeAttr('checked');
						activeElement.toggleClass(options.activeClass, isActive);
					});
					if (!isInput) {
						element.bind(options.toggleEvent, function () {
							var viewValue = directive == 'radio' ? trueValue : controller.$modelValue ? $helpers.parseConstant(controller.$modelValue) == trueValue ? falseValue : trueValue : trueValue;
							controller.$setViewValue(viewValue);
							scope.$apply();
						});
					}
				}
			};
		}])
	});
}(window, window.angular);
+function (window, angular, undefined) {
	'use strict';
	angular.module('ngQuantum.carousel', ['ngQuantum.services.helpers'])
		.run(['$templateCache', function ($templateCache) {
			'use strict';
			$templateCache.put('carousel/carousel.tpl.html',
				'<div class="carousel" ng-style="{width:$outerWidth}">'
				+ '<ol class="carousel-indicators">'
				+ '<li ng-repeat="item in items"  indicator-transclude="item" ng-class="{active: item.active}" ng-click="item.select($index)">'
				+ '<span class="indicator-no">{{$index + 1}}</span>'
				+ '</li>'
				+ '</ol>'
				+ '<div class="carousel-inner" ng-transclude ng-style="{height:$innerHeight}"></div>'
				+ '<div class="carousel-control left"  ng-click="$prev()">'
				+ '<span class="icon-prev"></span>'
				+ '</div>'
				+ '<div class="carousel-control right" ng-click="$next()">'
				+ '<span class="icon-next"></span>'
				+ '</div>'
				+ '</div>'
			);
		}])
		.provider('$carousel', function () {
			var defaults = this.defaults = {
				effect: 'slide-left-right',
				type: 'carousel',
				speed: 'fastest',
				prefixEvent: 'carousel',
				directive: 'nqCarousel',
				instanceName: 'carousel',
				keyboard: true,
				hoverStop: true,
				showIndicator: true,
				showPrevNext: true,
				showPause: true,
				showPlay: true,
				autoPlay: true,
				outerWidth: '650px',
				innerHeight: '405px',
				interval: 5000
			};
			this.$get = ['$timeout', '$interval', '$filter', '$compile', '$sce', '$animate',
				function ($timeout, $interval, $filter, $compile, $sce, $animate) {
					function CarouselFactory($element, $scope, config) {

						var $carousel = {},
							options = $carousel.$options = angular.extend({}, defaults, config),
							items = $carousel.items = $scope.items = [];
						var lastIndex = $carousel.$lastIndex = 0;
						var stopFunc;
						angular.forEach(['next', 'prev', 'play', 'pause'], function (value) {
							$scope['$' + value] = function (evt) {
								$carousel[value](evt);
							}
						})
						angular.forEach(['outerWidth', 'innerHeight'], function (value) {
							$scope['$' + value] = options[value];
						})
						if ($element.hasClass('thumb-navigation') || $element.hasClass('number-navigation')) {
							$carousel.$watchIndicator = true;
						}
						$carousel.init = function () {
							if (options.autoPlay) {
								$carousel.play()
								hoverStop();
							}
							$timeout(function () {
								if (parseInt($scope.$outerWidth) > $element.width()) {
									$scope.$innerHeight = ((parseInt($scope.$innerHeight) / parseInt($scope.$outerWidth)) * $element.width()) + 'px';
								}
							}, 800)
						};
						$carousel.select = function (index) {
							var selectedItem = items[index];
							angular.forEach(items, function (item) {
								if (item.active && item !== selectedItem) {
									item.active = false;
									item.activeClasses = '';
								}
							});
							if (selectedItem) {
								selectedItem.active = true;
								lastIndex = $carousel.$lastIndex = index;
							}

						};
						$carousel.pause = function () {
							$interval.cancel(stopFunc)
						};
						$carousel.play = function () {
							stopFunc = $interval($carousel.next, options.interval)
						};
						$carousel.next = function (evt) {
							var i = lastIndex < items.length - 1 ? lastIndex + 1 : 0
							$carousel.select(i);
						};
						$carousel.prev = function () {
							var i = lastIndex > 0 ? lastIndex - 1 : items.length - 1
							$carousel.select(i);
						};
						$carousel.addItem = function (item) {
							items.push(item);
							if (items.length === 1) {
								item.active = true;
							} else if (item.active) {
								$carousel.select(items.indexOf(item));
							}
						};
						$carousel.removeItem = function (item) {
							var index = items.indexOf(item);
							if (item.active && items.length > 1) {
								var newActiveIndex = index == items.length - 1 ? index - 1 : index + 1;
								$carousel.select(newActiveIndex);
							}
							items.splice(index, 1);
						};
						$carousel.init();

						function hoverStop() {
							if (options.hoverStop) {
								$element.on('mouseenter', function () {
									$carousel.pause();
								})
								$element.on('mouseleave', function () {
									$carousel.play();
								})
							}
						}

						return $carousel;
					}
					return CarouselFactory;
				}
			];
		})
		.directive('nqCarousel', ['$carousel', '$helpers', function ($carousel, $helpers) {
			return {
				restrict: 'EA',
				transclude: true,
				replace: true,
				scope: {},
				templateUrl: 'carousel/carousel.tpl.html',
				controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
					var that = this, options = {};
					angular.forEach(['effect', 'speed', 'interval', 'keyboard', 'hoverStop', 'autoPlay', 'outerWidth', 'innerHeight'],
						function (key) {
							angular.isDefined($attrs[key]) && (options[key] = $helpers.parseConstant($attrs[key]))
						})
					var ctrl = new $carousel($element, $scope, options)
					that = angular.extend(that, ctrl)
					return that;
				}]
			};
		}])
		.directive('carouselItem', ['$parse', function ($parse) {
			return {
				require: '^nqCarousel',
				restrict: 'EA',
				replace: true,
				template: '<div class="item" carousel-item-transclude="" ng-swipe-left="$parent.$next()"  ng-swipe-right="$parent.$prev()"></div>',
				transclude: true,
				scope: {
					active: '=?',
					heading: '@',
				},
				controller: function () {
				},
				compile: function (elm, attrs, transclude) {
					return function postLink(scope, elm, attrs, controller) {
						scope.effect = controller.$options.effect;
						scope.speed = controller.$options.speed;
						angular.isDefined(attrs.effect) && (scope.effect = attrs.effect)
						angular.isDefined(attrs.speed) && (scope.effect = attrs.speed)


						scope.select = function (index) {
							index = index || scope.$index || 0;
							controller.select(index);
						};
						controller.addItem(scope);
						scope.$on('$destroy', function () {
							controller.removeItem(scope);
						});

						scope.$transcludeFn = transclude;
					};
				}
			};
		}])

		.directive('indicatorTransclude', [function () {
			return {
				restrict: 'A',
				require: '^nqCarousel',
				link: function (scope, elm, attrs, controller) {
					var item = scope.$eval(attrs.indicatorTransclude);
					if (controller.$watchIndicator && scope.$first) {
						controller.thumbWidth = elm.width();
						controller.thumbHeight = elm.height();
						controller.visibleThumb = parseInt((elm.closest('.carousel').width() - 100) / controller.thumbWidth)
					}
					scope.$watch(function () { return item.thumbImage }, function (image) {
						if (image) {
							angular.element(image).on('load', function () {
								var c = document.createElement("canvas"),
									w = controller.thumbWidth,
									h = controller.thumbHeight,
									ow = controller.$options.outherWidth;
								c.width = w - 2; c.height = h - 2;
								c.getContext("2d").drawImage(this, 0, 0, w - 2, h - 2);

								elm.html(c)
							});
						}
					});
					if (controller.$watchIndicator) {
						scope.$watch(function () { return controller.$lastIndex }, function (index) {
							if (controller.visibleThumb > 0) {
								if (scope.$index + controller.visibleThumb < (index + 2))
									elm.hide();
								else if (elm.css('display') == 'none')
									elm.show();
							}
						});
					}
				}
			};
		}])
		.directive('carouselItemTransclude', ['$animate', '$timeout', function ($animate, $timeout) {
			return {
				restrict: 'A',
				require: '^carouselItem',
				link: function (scope, elm, attrs, controller) {
					scope.$watch('$transcludeFn', function (value) {
						scope.$transcludeFn(scope.$parent, function (contents) {
							angular.forEach(contents, function (node) {
								var nodeEl = angular.element(node)
								if (nodeEl.hasClass('thumb-image')) {
									scope.thumbImage = nodeEl;
								}
								else if (nodeEl.hasClass('generate-thumb')) {
									scope.thumbImage = nodeEl;
									elm.append(node);
								}
								else
									elm.append(node);
							});
						});
					});
					scope.$watch('active', function (value) {
						value ? show() : hide();
					});
					function show() {
						elm.show();
						if (scope.effect) {
							elm.addClass(scope.speed)
							$animate.addClass(elm, scope.effect).then(function () {
							});
						}

					}
					function hide() {
						if (scope.effect) {

							$animate.removeClass(elm, scope.effect).then(function () {
								elm.hide();
							});
							elm.animationEnd(function (evt) {
								!scope.active && elm.hide();
							});
						}
						else
							elm.hide();
					}
				}
			};
		}]);
}(window, window.angular);
+function (window, angular, undefined) {
	'use strict';
	angular.module('ngQuantum.collapse', [])
		.provider('$collapse', function () {
			var defaults = this.defaults = {
				dimension: 'height',
				collapsed: true
			};
			this.$get = ['$timeout', '$rootScope',
				function ($timeout, $rootScope) {
					function Factory(target, element, config) {
						var $collapse = {}, position, size, dimension, collapsed;
						var options = $collapse.$options = angular.extend({}, defaults, config);
						dimension = options.dimension;
						$collapse.collapsed = options.collapsed;
						target.addClass('collapse');
						if (!$collapse.collapsed) {
							target.addClass('in');
							size = target[dimension]();
						}
						function toggle() {
							if ($collapse.collapsed) {
								position = target[0].style.position || '';
								target.css('position', 'absolute').show();
								var dm = dimension == 'height' ? 'outerHeight' : 'outerWidth';
								size = target[dm]();

								target.css('display', '')[dimension](0).css('position', position);
								target.addClass('in collapsing');
								setTimeout(function () {
									target[dimension](size)
										.transitionEnd(function () {
											target.removeClass('collapsing');
											$collapse.collapsed = false;
											options.onToggle && options.onToggle(false);
											target[dimension]('');
										});
								}, 1)

							} else {
								size = target[dimension]();
								target[dimension](size)
								setTimeout(function () {
									target.addClass('collapsing')[dimension](0)
										.transitionEnd(function () {
											target[dimension]('');
											target.removeClass('collapsing').removeClass('in').css(dimension, '');
											$collapse.collapsed = true;
											options.onToggle && options.onToggle(true);
										});
								}, 1)

							}
						}
						element && element.on('click', function (evt) {
							evt.preventDefault();
							evt.stopPropagation();
							toggle();

						});
						options.checkRouting && $rootScope.$on('$locationChangeStart', function (event, viewConfig) {
							if (!$collapse.collapsed) {
								$collapse.collapsed = false;
								toggle();
							}

						});
						$collapse.toggle = toggle;
						return $collapse;
					}
					return Factory;
				}
			];
		})
		.directive('nqAccordion', function () {
			return {
				restrict: 'A',
				require: '?ngModel',
				compile: function (element, attr) {
					var model = attr.ngModel;
					if (!model)
						model = 'accordionModel' + Math.floor((Math.random() * 1000) + 1).toString();
					element.removeAttr('ng-model');
					var children = element.find('> .panel');

					angular.forEach(children, function (child, key) {
						var childEl = angular.element(child),
							target = childEl.find('.panel-collapse');
						if (target.length) {
							var id = target.attr('id')
							if (!id) {
								id = model + Math.floor((Math.random() * 1000) + 1).toString()
								target.attr('id', id)
							}
							var link = childEl.find('.panel-title > a');
							if (!link.length)
								link = childEl.find('.panel-title');
							if (!link.length)
								link = childEl.find('.panel-heading');
							if (link.length) {
								link.attr('target-index', key);
								link.attr('target-id', '#' + id);
								link.attr('data-ng-click', model + "=" + model + "==" + key + "?" + 20000000 + ":" + key)
								link.attr('ng-model', model);
								link.attr('nq-collapse', '');
							}

						}


					});

				}
			};
		})
		.directive("nqCollapse", ['$collapse', function ($collapse) {
			return {
				restrict: 'EAC',
				require: '?ngModel',
				compile: function (tElm, tAttrs, transclude) {
					var collapsed = true, target = angular.element(tAttrs.targetId),
						dimension = angular.isDefined(tAttrs.dimension) && tAttrs.dimension == 'width' ? tAttrs.dimension : 'height';
					if (angular.isDefined(tAttrs.collapsed) && (tAttrs.collapsed == 'false' || tAttrs.collapsed == false))
						collapsed = false;
					var options = {
						collapsed: collapsed,
						dimension: dimension,
						checkRouting: tAttrs.checkRouting || tElm.hasClass('navbar-toggle')
					}
					var index = tAttrs.targetIndex ? parseInt(tAttrs.targetIndex) : 0,
						collapse,
						elm = !angular.isDefined(tAttrs.ngModel) ? tElm : null;
					if (target.length) {
						collapse = new $collapse(target, elm, options)
					}

					return function postLink(scope, element, attr, controller) {
						collapse && angular.isDefined(tAttrs.ngModel) && scope.$watch(attr.ngModel, function (value, old) {
							if (value == undefined)
								return;
							if (value == index || !collapse.collapsed)
								collapse.toggle();
						})

					}
				}
			};
		}]);
}(window, window.angular);
+function (window, angular, undefined) {
	'use strict';
	angular.module('ngQuantum.colorpicker', ['ngQuantum.popMaster'])
		.run(['$templateCache', function ($templateCache) {
			'use strict';
			$templateCache.put('colorpicker/colorpicker.tpl.html',
				'<div class="popover colorpicker">'
				+ '<ul class="nav palettes-list clearfix">'
				+ '<li ng-repeat="color in palettes"  ng-click="$parent.$select($index)">'
				+ '<span class="color-pick titip-top" data-title="{{color}}" ng-style="{\'background-color\':color}"></span>'
				+ '</li>'
				+ '</ul>'
				+ '<div class="clearfix">'
				+ '<span class="color-pick titip-top" data-title="{{selectedColor}}" ng-style="{\'background-color\':selectedColor}"></span>&nbsp;&nbsp;'
				+ '<span class="color-pick titip-top" ng-click="$select(\'transparent\')" data-title="Set Transparent" style="background-color:transparent;"></span>'
				+ '<small class="pull-right color-more-label" ng-click="$showPicker()">{{$options.moreText || \'More\'}} <i ng-class="$options.iconDown" class="angle-down"></i><i ng-class="$options.iconUp" class="angle-up"></i></small>'
				+ '</div>'
				+ '<div class="color-selector-panel">'
				+ '<ul class="clearfix nav-color-current">'
				+ '<li class="color-current-label">Current</li>'
				+ '<li><span class="color-current"  ng-style="{\'background-color\':selectedColor || newColor }"></span><span class="color-new" ng-style="{\'background-color\':newColor || selectedColor}"></span></li>'
				+ '<li class="color-new-label">New</li>'
				+ '</ul>'
				+ '<div class="clearfix">'
				+ '<div class="color-saturation"><span class="sat-point"></span></div>'
				+ '<div class="color-hue"><span class="hue-slider"></span></div>'
				+ '</div>'
				+ '<div class="clearfix alpha-row">'
				+ '<div class="color-alpha"><span class="alpha-slider titip-top titip-yellow titip-xs"><span class="titip-content">{{$alphaValue}}%</span></span></div>'
				+ '<div class="color-button"><button type="button" class="btn btn-default" ng-click="$select()">ok</button></div>'
				+ '</div>'
				+ '</div>'
				+ '</div>'
			)
		}])


		.provider('$colorPicker', function () {
			var defaults = this.defaults = {
				palette: [
					'#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF',
					'#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF',
					'#F7C6CE', '#FFE7CE', '#FFEFC6', '#D6EFD6', '#CEDEE7', '#CEE7F7', '#D6D6E7', '#E7D6DE',
					'#E79C9C', '#FFC69C', '#FFE79C', '#B5D6A5', '#A5C6CE', '#9CC6EF', '#B5A5D6', '#D6A5BD',
					'#E76363', '#F7AD6B', '#FFD663', '#94BD7B', '#73A5AD', '#6BADDE', '#8C7BC6', '#C67BA5',
					'#CE0000', '#E79439', '#EFC631', '#6BA54A', '#4A7B8C', '#3984C6', '#634AA5', '#A54A7B',
					'#9C0000', '#B56308', '#BD9400', '#397B21', '#104A5A', '#085294', '#311873', '#731842',
					'#630000', '#7B3900', '#846300', '#295218', '#083139', '#003163', '#21104A', '#4A1031'
				],
				paletteOnly: true,
				showAlpha: true,
				defaultColor: '#000000',
				effect: 'sing',
				typeClass: 'popover',
				prefixClass: 'colorpicker',
				prefixEvent: 'colorpicker',
				instanceName: 'colorpicker',
				placement: 'bottom-left',
				template: 'colorpicker/colorpicker.tpl.html',
				trigger: 'click',
				container: 'body',
				showArrow: true,
				allowWrite: false,
				autoHide: false,
				iconDown: 'fic fu-angle-d',
				iconUp: 'fic fu-angle-u',
				moreText: 'More',
				html: true,
				displayReflow: false,
				fireEmit: true,
				keyboard: true,
				overseeingTarget: true
			};
			this.$get = ['$rootScope', '$popMaster', '$document', '$color', '$mouse', '$helpers',
				function ($rootScope, $popMaster, $document, $color, $mouse, $helpers) {
					function Factory(element, config, attr) {
						var $picker = {}, alpha, hue, saturation, target, count = 0, sizes, hueSlider, satPoint, alphaSlider;
						config = $helpers.parseOptions(attr, config);
						var options = angular.extend({}, defaults, config);
						var $picker = new $popMaster(element, options);
						var scope = $picker.$scope;
						options = $picker.$options = $helpers.observeOptions(attr, $picker.$options);
						scope.$$postDigest(function () {
							scope.palettes = options.palette;
							scope.$select = $picker.select;
							scope.$alphaValue = 100;
							scope.$options = $picker.$options;
						});
						scope.$showPicker = function () {
							$picker.$target.toggleClass('picker-open');
							if ($picker.$target.hasClass('picker-open')) {
								bindMouse();
								setPositions();
							}
							else
								unbindMouse();

						}
						var init = $picker.init;
						$picker.init = function () {
							init();
							findElement();
							scope.selectedColor = scope.newColor = scope.selectedColor || options.defaultColor || '#FF0000';
							scope.$color.setColor(scope.selectedColor);
						}
						var show = $picker.show;
						$picker.show = function () {
							return show();
						}
						var hide = $picker.hide;
						$picker.hide = function () {
							var promise = hide();
							unbindMouse();
							$picker.$target.removeClass('picker-open');
							return promise;
						}
						var destroy = $picker.destroy
						$picker.destroy = function () {
							destroy();
							unbindMouse();
							scope.$destroy();
						}
						$picker.select = function (index) {
							var color = scope.selectedColor || '#FF0000';
							if (index) {
								if (index == 'transparent')
									color = 'transparent';
								else {
									color = scope.palettes[index];
									scope.$color.setColor(color);
								}

							}
							else if (scope.$color) {
								if (scope.$color.value.a == 1)
									color = scope.$color.hex()
								else
									color = scope.$color.rgba();
								$picker.$target.removeClass('picker-open');
							}
							scope.selectedColor = color;
						}
						function findElement() {
							target = $picker.$target;
							if (!target && count < 10) {
								setTimeout(function () {
									findElement()
									count++;
								}, 50)
							}
							else {
								!scope.$color && (scope.$color = $color)
								hue = target.find('.color-hue');
								alpha = target.find('.color-alpha');
								saturation = target.find('.color-saturation');
								hueSlider = hue.find('.hue-slider');
								satPoint = saturation.find('.sat-point');
								alphaSlider = alpha.find('.alpha-slider');
							}
						}

						function bindMouse() {
							if (!sizes)
								findSizes();
							hueMouse();
							saturationMouse();
							alphaMouse();
						}
						function unbindMouse() {
							$mouse.offDown(saturation)
							$mouse.offDown(satPoint);
							$mouse.offDown(hue)
							$mouse.offDown(hueSlider);
							$mouse.offDown(alpha)
							$mouse.offDown(alphaSlider);
						}
						function hueMouse() {
							$mouse.down(hue, slideHue)
							$mouse.down(hueSlider, function (event) {
								$mouse.offMove($document, slideHue);
								$mouse.move($document, slideHue);
								var upHandler = function (event) {
									$mouse.offMove($document, slideHue);
									$mouse.offUp($document, upHandler);
								};
								$mouse.up($document, upHandler)
							})

						}
						function saturationMouse() {
							$mouse.down(saturation, dragSaturation)
							$mouse.down(satPoint, function (event) {
								$mouse.offMove($document, dragSaturation)
								$mouse.move($document, dragSaturation);
								var upHandler = function (event) {
									$mouse.offMove($document, dragSaturation)
									$mouse.offUp($document, upHandler);
								};
								$mouse.up($document, upHandler)
							})


						}
						function alphaMouse() {
							$mouse.down(alpha, slideAlpha)
							$mouse.down(alphaSlider, function (event) {
								$mouse.offMove($document, slideAlpha)
								$mouse.move($document, slideAlpha);
								var upHandler = function (event) {
									$mouse.offMove($document, slideAlpha)
									alphaSlider.removeClass('titip-active');
									$mouse.offUp($document, upHandler)
								};
								$mouse.up($document, upHandler)
							})


						}
						function slideHue(event) {
							var y = $mouse.relativeY(event, hue);
							y = y > sizes.hh ? sizes.hh : y < 0 ? 0 : y;
							hueSlider.css({ top: y - (sizes.hsh / 2) });
							setHue((y / sizes.hh));
						}
						function dragSaturation(event) {
							var pos = $mouse.relativePos(event, saturation);
							var x = pos.left, y = pos.top;
							y = y > sizes.hh ? sizes.hh : y < 0 ? 0 : y;
							x = x > sizes.aw ? sizes.aw : x < 0 ? 0 : x;

							satPoint.css({ left: x - (sizes.spw / 2), top: y - (sizes.sph / 2) });
							setSaturation((x / sizes.sw), 1 - (y / sizes.sh));
						}
						function slideAlpha(event) {
							alphaSlider.addClass('titip-active')
							var x = $mouse.relativeX(event, alpha);
							x = x > sizes.aw ? sizes.aw : x < 0 ? 0 : x;
							alphaSlider.css({ left: x - (sizes.asw / 2) });
							setAlpha((x / sizes.aw));
						}

						function findSizes() {
							sizes = {
								hh: hue.height(),
								hsh: hueSlider.outerHeight(),
								sw: saturation.width(),
								sh: saturation.height(),
								sph: satPoint.outerHeight(),
								spw: satPoint.outerWidth(),
								aw: alpha.width(),
								asw: alphaSlider.outerWidth()
							}
						}
						function drawAlphaBg() {
							var color = scope.$color.hex();
							alpha.css('background-image', 'linear-gradient(to right, rgba(255,255,255, 0), ' + color + ')')
							scope.newColor = scope.$color.rgba();
							!scope.$$phase && scope.$apply(function () {
								scope.newColor = scope.$color.rgba();
							})

						}
						function setPositions() {
							if (!sizes)
								findSizes();
							var satpos = {
								left: (scope.$color.value.s * sizes.sw) - (sizes.spw / 2),
								top: ((1 - scope.$color.value.b) * sizes.sw) - (sizes.sph / 2)
							}
							satPoint.css(satpos)
							hueSlider.css({ top: (scope.$color.value.h * sizes.hh) - (sizes.hsh / 2) });
							alphaSlider.css({ left: (scope.$color.value.a * sizes.aw) - (sizes.asw / 2) });
							scope.$alphaValue = parseInt(scope.$color.value.a * 100);
							saturation.css('background-color', $color.toHex(scope.$color.value.h, 1, 1, 1))
							drawAlphaBg();
						}
						function setHue(value) {
							scope.$color.setHue(value);
							saturation.css('background-color', $color.toHex(value, 1, 1, 1))
							drawAlphaBg()
						}
						function setSaturation(sat, bright) {
							scope.$color.setSaturation(sat);
							scope.$color.setLightness(bright);
							drawAlphaBg();
						}
						function setAlpha(value) {
							scope.$color.setAlpha(value);
							scope.$apply(function () {
								scope.$alphaValue = parseInt(value * 100);
							})
							drawAlphaBg();
						}
						return $picker;
					}
					return Factory;
				}
			];
		})
		.directive('nqColorPicker', ['$colorPicker', function ($colorPicker) {
			return {
				restrict: 'AC',
				require: 'ngModel',
				link: function postLink(scope, element, attr, controller) {
					var options = {
						$scope: scope.$new()
					};
					var picker = new $colorPicker(element, options, attr)
					scope.$watch(attr.ngModel, function (newVal, oldVal) {
						if (newVal && (newVal !== picker.$scope.selectedColor)) {
							picker.$scope.selectedColor = newVal;
						}
					})

					picker.$scope.$watch('selectedColor', function (newVal, oldVal) {
						if (newVal && (newVal !== oldVal)) {
							controller.$setViewValue(picker.$scope.selectedColor);
							controller.$render();
						}
					})
					scope.$on('$destroy', function () {
						picker && picker.destroy();
						picker = null

					})
				}
			};
		}]);
}(window, window.angular);
(function (moment) {
	if (!moment)
		return;
	moment.fn.clearTime = function () {
		this.hours(0);
		this.minutes(0);
		this.seconds(0);
		this.milliseconds(0);
		return this;
	};
	moment.fn.isWeekend = function () {
		var d = this.day()
		return (d == 6 || d == 0) || false;
	};
	moment.fn.isToday = function () {
		return (this.clone().clearTime().valueOf() == moment().clearTime().valueOf());
	};
	moment.fn.toObject = function () {
		var m = this;
		return {
			year: m.year(),
			month: m.month(),
			date: m.date(),
			hour: m.hours(),
			minute: m.minutes(),
			second: m.seconds(),
			millisecond: m.milliseconds()
		}
	}

})(window.moment);
+function (window, angular, undefined) {
	'use strict';
	angular.module('ngQuantum.datepicker', [
		'ngQuantum.popMaster'
	])
		.run(['$templateCache', function ($templateCache) {
			'use strict';
			$templateCache.put('datepicker/datepicker.tpl.html',
				"<div tabindex=\"-1\" class=\"calendar-panel\" role=\"listbox\"><div tabindex=\"-1\" class=\"calendar-header\" role=\"listbox\"></div><div tabindex=\"-1\" class=\"calendar-body\" role=\"listbox\"></div><div tabindex=\"-1\" class=\"calendar-footer\" role=\"listbox\"></div></div>"
			);

		}])
		.provider('$datepicker', function () {
			var defaults = this.defaults = {
				format: 'MM-DD-YYYY',
				timeFormat: 'HH:mm:ss',
				headerFormat: 'MMMM YYYY',
				timepicker: false,
				datepicker: true,
				rangepicker: false,
				timeView: false,
				showEvents: false,
				weekNumber: false,
				minDate: false,
				minDateFrom: false,
				maxDate: false,
				startDate: false,
				minHour: 0,
				maxHour: 23,
				divideHour: 4,
				defaultTime: false,
				timesSet: [], //to do
				todayButton: true,
				rangeType: 'day',
				minRange: 1,
				maxRange: false,
				defaultSelect: true, //to do
				allowBlank: false, //to do
				showYears: true,
				minYear: 1950,
				maxYear: 2050,
				dayOfWeekStart: 1,
				disableWeekends: false,
				disableWeekdays: [],
				specialDays: [], //to do
				dayHeader: 'shortest',
				effect: 'flip-y',
				typeClass: 'datepicker',
				prefixClass: 'calendar',
				prefixEvent: 'datepicker',
				instanceName: 'datepicker',
				placement: 'bottom-left',
				template: 'datepicker/datepicker.tpl.html',
				trigger: 'click',
				container: 'body',
				showArrow: true,
				allowWrite: false,
				autoHide: true,
				html: true,
				displayReflow: false,
				fireEmit: true,
				keyboard: true, //to do
				show: false,
				inline: false,
				theme: 'default',
				selectable: true,
				readonly: true,
				overseeingTarget: true,
				modelType: 'date',
				nextIcon: 'fic fu-angle-r',
				prevIcon: 'fic fu-angle-l',
				todayIcon: 'fic fu-restore',
				closeIcon: 'fic fu-cross',
				timeIcon: 'fic fu-time',
				downIcon: 'fic fu-angle-d',
				upIcon: 'fic fu-angle-u'
			};
			this.$get = [
				'$compile',
				'$popMaster',
				'$parse',
				'$helpers',
				'$timeout',
				function ($compile, $popMaster, $parse, $helpers, $timeout) {
					function Factory(element, config, attr, ngModel) {
						config = $helpers.parseOptions(attr, config);
						var options = angular.extend({}, defaults, config);
						if (options.inline) {
							options.show = true;
							options.trigger = false;
							options.showArrow = false;
							options.container = 'self';
							element.addClass('calendar-inline');
							options.effect = false;
							options.autoHide = false;
							options.readonly = false;
						}
						var $picker = new $popMaster(element, options);
						var scope = $picker.$scope; var $target, $header, $body, $footer, yearSelector, table, tbody, initialized, lastCacheKey, keyTarget;

						scope.$options = options = $helpers.observeOptions(attr, options);

						$picker.caches = {};

						angular.forEach(['next', 'before', 'today', 'gotoYear'], function (value) {
							scope['$' + value] = function (evt) {
								scope.$$postDigest(function () {
									$picker[value](evt);
								});
							}
						})
						scope.$gotoYear = function (val, evt) {
							if (evt) {
								evt.preventDefault();
								$picker.preventHide = true;
							}

							scope.$$postDigest(function () {
								$picker.gotoYear(val)
							});
						}
						scope.$select = function (val, type) {
							scope.$$postDigest(function () {
								$picker.select(val, type)
							});
						}
						scope.$setTime = function (val) {
							scope.$$postDigest(function () {
								$picker.setTime(val)
							});
						}
						scope.$changeTime = function (dir, type, val) {
							scope.$$postDigest(function () {
								$picker.changeTime(dir, type, val)
							});
						}

						var init = $picker.init;
						$picker.init = function () {
							optimize();
							init();
							if (!initialized) {
								initialized = true;
								buildScope();
							}
							if (!options.allowWrite) {
								element.on('keydown', function () {
									return false;
								})
							}
							$target = $picker.$target;
						}
						var show = $picker.show;
						$picker.show = function () {
							if (!$picker.$builded) {
								buildFirst();
							}
							var promise = show();
							promise && promise.then(function () {
								formatPicker();
								$target.focus();
							})
							if (options.keyboard && $picker.$target) {
								angular.element(document).off('keydown', $picker.$onKeyDown);
								angular.element(document).on('keydown', $picker.$onKeyDown);
							}
							return promise;
						}
						var hide = $picker.hide;
						$picker.hide = function () {
							if ($picker.preventHide) {
								$picker.preventHide = false;
								return false;
							}
							var promise = hide();
							promise && promise.then(function () {
								if (scope.$timeViewActive && options.datepicker)
									scope.$toggleTimepicker();
								element && element.focus();
							})
							if (options.keyboard && $picker.$target) {
								angular.element(document).off('keydown', $picker.$onKeyDown);
							}
							return promise;
						}
						var destroy = $picker.destroy;
						$picker.destroy = function () {
							destroy();
							scope.$destroy();
						}
						$picker.next = function () {
							$picker.changeDate('up', 'month', 1)
						}
						$picker.before = function () {
							$picker.changeDate('down', 'month', 1)
						}
						$picker.changeDate = function (dir, type, val) {
							var v = !val ? 1 : angular.isNumber(val) ? val : window.isNaN(parseInt(val)) ? 1 : parseInt(val);
							v = dir == 'down' ? -v : v;
							type = type || 'day';
							var dt = scope.currentDate.clone().add(v, type);
							if (scope.minDate && dt.clone().endOf('month') < scope.minDate)
								return;
							if (scope.maxDate && dt.clone().startOf('month') > scope.maxDate)
								return;
							apply(function () {
								if (scope.minDate && dt < scope.minDate) {
									dt = scope.minDate.clone();
								}
								if (scope.maxDate && dt > scope.maxDate) {
									dt = scope.maxDate.clone();
								}
								if (options.disableWeekdays.length) {
									while (options.disableWeekdays.indexOf(dt.day()) > -1)
										dt.add(1, 'day')
								}
								scope.selectedDay = dt.month() + '-' + dt.date();
								scope.currentDate = dt.clone();
								fireChange(type)
								buildNew()
							});
						}
						$picker.today = function (evt) {
							if (evt) {
								evt.preventDefault();
								$picker.preventHide = true;
							}
							apply(function () {
								scope.currentDate = scope.minDate && scope.startDate < scope.minDate ? scope.minDate.clone() : scope.maxDate && scope.startDate > scope.maxDate ? scope.maxDate.clone() : scope.startDate.clone();
								buildNew()
								scope.modelSetted = true;
								renderModel();
								fireChange();
								scope.selectedDay = scope.currentDate.month() + '-' + scope.currentDate.date();
							})

						}
						$picker.gotoYear = function (val) {
							apply(function () {
								scope.currentDate.year(val);
								buildNew();
								scope.modelSetted = true;
								renderModel();
								fireChange('year')
							})

						}
						$picker.setTime = function (val) {
							var date = scope.currentDate.clone();
							var h = parseInt(val.split(':')[0]);
							var m = parseInt(val.split(':')[1]) || 0;
							if (window.isNaN(h))
								h = options.minHour;
							date.hour(h)
							date.minute(m)
							apply(function () {
								scope.currentDate = date;
								scope.modelSetted = true;
								renderModel();
								fireChange('time');
							})
							if (options.datepicker)
								scope.$toggleTimepicker();
							else if (options.autoHide)
								$picker.hide();
						}
						$picker.changeTime = function (dir, type, val) {
							var v = !val ? 1 : angular.isNumber(val) ? val : window.isNaN(parseInt(val)) ? 1 : parseInt(val);
							v = dir == 'down' ? -v : v;
							var dt = scope.currentDate.clone().add(v, type),
								dth = dt.hour();
							if (dth >= options.minHour && dth <= options.maxHour) {
								scope.currentDate = dt.clone();
								scope.modelSetted = true;
								renderModel();
								fireChange(type)
							}
						}
						$picker.$onKeyDown = function (e) {
							if (!/(13|37|38|39|40)/.test(e.keyCode))
								return true;
							if (!e.isDefaultPrevented()) {

								var timeView = scope.$timeViewActive,
									dir, type;
								var code = e.keyCode, evt = e;
								if (!timeView) {
									e.preventDefault();
									switch (code) {
										case 37:
										case 38:
											dir = 'down';
											type = e.ctrlKey ? (code == 37 ? 'month' : 'year') : (code == 37 ? 'day' : 'week');
											break;
										case 39:
										case 40:
											dir = 'up'
											type = e.ctrlKey ? (code == 39 ? 'month' : 'year') : (code == 39 ? 'day' : 'week');
											break;
									}
									if (code == 13) {
										if (e.altKey)
											$picker.today();
										else
											renderModel();
									}
									else
										dir && type && $picker.changeDate(dir, type, 1);
								} else if (code == 13) {
									if (options.timepicker && options.datepicker && e.ctrlKey)
										scope.$toggleTimepicker();
									else if (e.target.tagName.toLowerCase() == 'a')
										angular.element(e.target).triggerHandler('click')
								}

							}
							return true;
						};
						function buildFirst(disablenew) {
							$target = $picker.$target;
							if (!$target)
								return;
							getElements($target);
							if (options.rangepicker)
								$target.addClass('picker-datarange')
							else if (options.timepicker)
								$target.addClass('picker-datetime')
							else
								$target.addClass('picker-date')
							if (options.datepicker)
								buildHeader();
							if (options.timepicker)
								buildTimeSelector();
							if (options.showYears && options.datepicker)
								buildYearSelector();
							if (options.datepicker && !disablenew)
								buildNew();
							if (options.timepicker && !options.datepicker)
								$picker.$builded = true;


						}
						function buildNew() {
							if (!$body) {
								buildFirst(true);
							}

							if (options.timepicker && !options.datepicker)
								return;
							var cachekey = cacheKey(scope.currentDate);
							if (lastCacheKey && cachekey == lastCacheKey)
								return;
							lastCacheKey = cachekey;
							var data = $picker.caches[cachekey];

							if (!data) {
								data = createCache(cachekey);
							}
							apply(function () {
								scope.dayArray = data.dayArray;
							})

							$body.find('td.selected').removeClass('selected');
							tbody.html(data.content);
							$compile($body)(scope);
							$picker.$builded = true;
						}
						function createCache(cachekey) {
							var start = scope.currentDate
							var dArr = [];
							var month = start.month();
							var mStart = start.clone().startOf('month');
							var mEnd = mStart.clone().endOf('month');
							var dow = parseInt(options.dayOfWeekStart);
							var wStart = mStart.clone().day(dow)
							var wEnd = mEnd.clone().day(dow)
							if (wStart > mStart)
								wStart.add(-7, 'day')
							if (wEnd <= mEnd)
								wEnd.add(7, 'day')

							var diff = wEnd.diff(wStart, 'day')
							for (var d = 0; d < diff; d++) {
								var day = wStart.clone().add(d, 'day');
								var item = {
									day: day.date(),
									month: day.month(),
									isWeekend: day.isWeekend()
								}
								if (options.disableWeekdays.length && options.disableWeekdays.indexOf(day.day()) > -1) {
									item.unselectable = true;
								}
								if (month != day.month()) {
									item.outMonth = true;
								}
								if (options.weekNumber)
									item.week = day.week();
								if (scope.minDate && day < scope.minDate)
									item.unselectable = true;
								if (scope.maxDate && day > scope.maxDate)
									item.unselectable = true;
								dArr.push(item);
							}
							$picker.caches[cachekey] = { 'dayArray': dArr };
							scope.dayArray = dArr;
							$picker.caches[cachekey].content = buildTable();
							return $picker.caches[cachekey];
						}
						function getElements(target) {
							$header = target.find('.calendar-header');
							$body = target.find('.calendar-body');
							$footer = target.find('.calendar-footer');
						}
						function detectDate(dDate, defaultDate) {
							var value = angular.isString(dDate) ? moment(dDate, options.format) : angular.isDate(dDate) ? moment(dDate) : moment.isMoment(dDate) ? dDate.clone() : defaultDate;
							return moment.isMoment(value) ? value : moment()
						}
						function optimize() {
							if (!options.datepicker && !options.timepicker)
								options.datepicker = true;
							if (!angular.isArray(options.disableWeekdays))
								options.disableWeekdays = [];
							if (options.disableWeekends)
								options.disableWeekdays = options.disableWeekdays.concat([0, 6])
							if (options.minDate) {
								if (options.minDate == 'today') {
									scope.minDate = moment();
								}
								else
									scope.minDate = detectDate(options.minDate, moment())
								options.minYear = scope.minDate.year();
								scope.minDate.clearTime();
							}
							if (options.maxDate) {
								scope.maxDate = detectDate(options.maxDate, moment())
								options.maxYear = scope.maxDate.year();
								scope.maxDate.clearTime();
							}

							if (options.startDate) {
								scope.startDate = detectDate(options.startDate, moment())
							}
							else
								scope.startDate = scope.minDate && moment() < scope.minDate ? scope.minDate.clone() : scope.maxDate && moment() > scope.maxDate ? scope.maxDate.clone() : moment();
							scope.currentDate = scope.startDate.clone();
							scope.format = options.format;
							if (options.disableWeekdays.length)
								while (options.disableWeekdays.indexOf(scope.currentDate.day()) > -1)
									scope.currentDate.add(-1, 'day');
							if (options.timepicker) {
								options.minHour = angular.isNumber(options.minHour) && (options.minHour >= 0) ? options.minHour : 8;
								options.maxHour = angular.isNumber(options.maxHour) && options.maxHour || 22;
								options.divideHour = angular.isNumber(options.divideHour) && options.divideHour || 4;
								(options.minHour < 0 || options.minHour > 23) && (options.minHour = 0)
									(options.maxHour > 24 || options.maxHour < 2) && (options.maxHour = 24)
								if (options.divideHour > 30)
									options.divideHour = 0;
								else
									while (60 % options.divideHour != 0)
										options.divideHour++;
								optimizeTime();
							}
							else {
								scope.currentDate.clearTime();
							}
							if (scope.currentDate.hour() < options.minHour)
								scope.currentDate.hour(options.minHour).minute(0).second(0)
							if (!options.defaultRange) {
								options.defaultRange = options.minRange;
							}
							scope.selectedDay = scope.currentDate.month() + '-' + scope.currentDate.date();
						}
						function buildTable() {
							if (!$body) {
								buildFirst(true);
							}
							if (!table) {
								table = angular.element('<table/>').addClass('calendar-table');
								var thead = angular.element('<thead/>').appendTo(table);
								tbody = angular.element('<tbody/>').appendTo(table)
								var tfoot = angular.element('<tfoot/>').appendTo(table);
								var names = options.dayHeader == 'shortest' ? moment.localeData()._weekdaysMin || moment.localeData()._weekdaysShort : moment.localeData()._weekdaysShort;
								if (options.dayOfWeekStart > 0) {
									var first = names.slice(options.dayOfWeekStart, 7)
									var cut = names.slice(0, options.dayOfWeekStart)
									names = first.concat(cut);
								}
								var trhead = angular.element('<tr><th>' + names.join('</th><th>') + '</th></tr>').appendTo(thead);
								if (options.weekNumber) {
									table.addClass('has-week-no')
									trhead.prepend('<th class="cal-week-no">W</th>')
								}

								var watch = function () { return table.width() };
								scope.$watch(watch, function () { })();
								scope.$watch(watch, function (newValue, oldValue) {
									setTimeout(function () {
										yearSelector && yearSelector.css('width', table.width());
									}, 0)
								})
								$body.html(table)
							}

							return buildTableBody();
						}
						function buildTableBody() {
							var tbody = angular.element('<tbody/>');
							var rows = parseInt(scope.dayArray.length / 7)
							if ((scope.dayArray.length % 7) > 0) rows++;
							var idx = 0;
							for (var r = 0; r < rows; r++) {
								var trdate = angular.element('<tr></tr>').appendTo(tbody);
								var last = (r + 1) * 7
								if (last > scope.dayArray.length)
									last = scope.dayArray.length;
								var rdates = scope.dayArray.slice(r * 7, last);
								if (options.weekNumber)
									trdate.append('<th class="cal-week-no">' + rdates[0].week + '</th>');
								angular.forEach(rdates, function (val, key) {
									var slday = val.month + '-' + val.day;
									var td = angular.element('<td cal-date-item="' + idx + '" ng-class="{selected:selectedDay==\'' + slday + '\'}">' + val.day + '</td>').appendTo(trdate);
									if (val.unselectable)
										td.addClass('unselectable')
									if (val.isWeekend)
										td.addClass('weekend')
									if (val.outMonth)
										td.addClass('out-month')
									idx++;
								})

							}

							return tbody.html();
						}
						function buildHeader() {
							var ul = '<table class="cal-header-table"><tr>' +
								'<td class="before"><button data-title="Before" class="titip-top" type="button" ng-click="$before()"><i ng-class="$options.prevIcon"></i></button></td>' +
								'<td class="date-head"><span>{{currentMonthTitle}}</span></td>' +
								'<td class="today"><button data-title="Today" class="titip-top" type="button" ng-click="$today($event)"><i ng-class="$options.todayIcon"></i></button></td>' +
								'<td class="next"><button data-title="Next" class="titip-top" type="button" ng-click="$next()"><i ng-class="$options.nextIcon"></i></button></td>' +
								'<td class="hide-cal"><button data-title="Close" class="titip-top" type="button" ng-click="$hide()"><i ng-class="$options.closeIcon"></i></button></td>' +
								'</tr></table>';
							ul = angular.element(ul)
							$compile(ul)(scope);
							$header.html(ul)
						}
						function buildYearSelector() {
							if (options.showYears) {
								yearSelector = angular.element('<div class="year-selector" ng-hide="yearsArray.length < 2" nq-scroll="" data-qo-axis="x" data-qo-bar-size="slimmest" data-qo-placement-offset="0" data-qo-visible="true"></div>').appendTo($footer);
								var inner = angular.element('<div class="selector-inner"></div>').appendTo(yearSelector);
								options.theme && yearSelector.attr('data-qo-theme', options.theme);
								getYearArray();
								inner.append('<a role="button" tabindex="1" id="year-{{year}}" ng-repeat="year in yearsArray" ng-click="$gotoYear(year, $event)" ng-class="{active:currentYear == year}"><span>{{year}}</span></a>');
								$picker.yearSelector = yearSelector;
								$compile(yearSelector)(scope);

							}

						}
						function getYearArray() {
							scope.yearsArray = [];
							for (var y = options.minYear; y <= options.maxYear; y++)
								scope.yearsArray.push(y)
						}
						function buildTimeSelector() {
							if (options.timepicker) {
								var dpCont = angular.element('<div role="presentation" tabindex="-1" class="dp-container clearfix"></div>').appendTo($body),
									tpCont = angular.element('<div class="tp-container clearfix"></div>').appendTo($body),
									tpSwicher = angular.element('<div class="tp-switcher" time-picker-switch="" data-time-icon="$options.timeIcon"  data-close-icon="$options.closeIcon"></div>').appendTo(tpCont),
									tpTemp = timePickerTemplate().appendTo(tpCont);

								$compile(tpCont)(scope);
								scope.timePickerTemp = $picker.timePickerTemp = tpTemp;
								$body = dpCont;

								scope.$toggleTimepicker = function () {
									apply(function () {
										scope.timePickerTemp.toggle();
										$picker.yearSelector && $picker.yearSelector.toggle();
										$header.toggle();
										dpCont.toggle();
										tpCont.toggleClass('tp-visible');
										scope.$timeViewActive = !scope.$timeViewActive;

										if (scope.$timeViewActive) {
											(options.timeView == 'list') && scrollTime();
											dpCont.focus();
										}

									});
								}
							}
						}
						function cacheKey(date) {
							return date.year() + date.month();
						}
						function scrollYear() {
							if ($picker.yearSelector) {
								$timeout(function () {
									var yelm = '#year-' + (scope.currentYear - 3)
									var bar = $picker.yearSelector.data('$scrollBar');
									bar && bar.scrollTo(yelm)
								}, 0)

							}
						}
						function scrollTime() {
							if ($picker.timeListContainer) {
								$timeout(function () {
									var yelm = $picker.timeListContainer.find('a.active')
									if (yelm.length) {
										var bar = $picker.timeListContainer.data('$scrollBar');
										var lval = yelm[0].offsetTop - 30;

										bar && bar.scrollTo(lval);
										yelm.first().focus();
									}
									else
										$picker.timeListContainer.find('a').first().focus()
								}, 0)

							}
						}
						function fireChange(type) {
							switch (type) {
								case 'date':
								case 'day':
								case 'month':
								case 'year':
									scope.$broadcast('pickerDateChanged');
									break;
								case 'hour':
								case 'second':
								case 'minute':
								case 'time':
									scope.$broadcast('pickerTimeChanged');
									break;
								default:
									scope.$broadcast('pickerDatetimeChanged');
									break;
							}
							apply(function () {
								scope.currentDateObject = scope.currentDate.toObject();
							})
						}
						function optimizeTime() {
							if (options.timeView == 'list') {
								options.format = options.format.replace(':ss', '').replace('ss', '');
								var hr = scope.currentDate.hour();
								if (hr < options.minHour)
									scope.currentDate.hour(options.minHour)
								else if (hr > options.maxHour)
									scope.currentDate.hour(options.maxHour)

								var m = scope.currentDate.minutes();
								m = m - (m % parseInt(60 / options.divideHour))
								scope.currentDate.minute(m)
								scope.currentDate.second(0)
								scope.currentTimeString = scope.currentDate.format('HH:mm');
							}
						}
						function timePickerTemplate() {
							var timePicker = angular.element('<div class="cal-timepicker"></div>');
							var hh = options.format.indexOf('HH') > -1,
								mm = options.format.indexOf('mm') > -1,
								ss = options.format.indexOf('ss') > -1;
							if (options.timeView != 'list') {
								var tableTime = '<table class="tp-table"><tbody><tr>';
								tableTime += hh ? '<td><button ng-class="\'btn-\' + $options.theme" type="button" class="btn tp-up" ng-click="$changeTime(\'up\',\'hour\')"><i ng-class="$options.upIcon"></i></button></td>' : ''
								tableTime += hh ? '<td class="tp-seperator"></td>' : '';
								tableTime += mm ? '<td><button ng-class="\'btn-\' + $options.theme" type="button" class="btn tp-up" ng-click="$changeTime(\'up\',\'minute\')"><i ng-class="$options.upIcon"></i></button></td>' : '';
								tableTime += mm ? '<td class="tp-seperator"></td>' : '';
								tableTime += ss ? '<td><button ng-class="\'btn-\' + $options.theme" type="button" class="btn tp-up" ng-click="$changeTime(\'up\',\'second\')"><i ng-class="$options.upIcon"></i></button></td>' : '';
								tableTime += '</tr><tr>';
								tableTime += hh ? '<td tp-bind-time="hour"></td>' : '';
								tableTime += hh ? '<td class="tp-seperator">:</td>' : '';
								tableTime += mm ? '<td tp-bind-time="minute"></td>' : '';
								tableTime += mm ? '<td class="tp-seperator">:</td>' : '';
								tableTime += ss ? '<td tp-bind-time="second"></td>' : '';
								tableTime += '</tr><tr>';
								tableTime += hh ? '<td><button ng-class="\'btn-\' + $options.theme" type="button" class="btn tp-down" ng-click="$changeTime(\'down\',\'hour\')"><i ng-class="$options.downIcon"></i></button></td>' : '';
								tableTime += hh ? '<td class="tp-seperator"></td>' : '';
								tableTime += mm ? '<td><button ng-class="\'btn-\' + $options.theme" type="button" class="btn tp-down" ng-click="$changeTime(\'down\',\'minute\')"><i ng-class="$options.downIcon"></i></button></td>' : '';
								tableTime += mm ? '<td class="tp-seperator"></td>' : ''
								tableTime += ss ? '<td><button ng-class="\'btn-\' + $options.theme" type="button" class="btn tp-down" ng-click="$changeTime(\'down\',\'second\')"><i ng-class="$options.downIcon"></i></button></td>' : '';
								tableTime += '</tr></tbody></table>';
								timePicker.append(tableTime)
							}
							else {
								var times = [];
								if (!options.timesSet.length) {
									var min = options.minHour,
										max = options.maxHour,
										dvd = options.divideHour;

									var ratio = 60 / dvd;
									for (var h = min; h < max; h++)
										for (var s = 0; s < dvd; s++) {
											var rs = s * ratio;
											var item = h < 10 ? '0' + h : h;
											item += ':'
											item += rs < 10 ? '0' + rs : rs;
											times.push(item)
										}
									times.push(max + ':00')
								}
								else {
									angular.forEach(options.timesSet, function (val) {
										val = val.replace(' ', '')
										validateHhMm(val) && times.push(val)
									})
								}
								scope.timesList = times;
								var timeListContainer = angular.element('<div class="tp-time-list" nq-scroll="" data-qo-bar-size="slimmest" data-qo-placement-offset="0" data-qo-visible="true"><a class="tp-time" role="button" tabindex="1" ng-repeat="time in timesList" tp-time-list-item="time"  ng-class="{active:$parent.currentTimeString == time}"></a></div>')
								options.theme && timeListContainer.attr('data-qo-theme', '$options.theme');
								timePicker.append(timeListContainer)
								$picker.timeListContainer = timeListContainer;
							}
							return timePicker;
						}
						function validateHhMm(val) {
							return /^([0-1]?[0-9]|2[0-4]):([0-5][0-9])(:[0-5][0-9])?$/.test(val);
						}
						function renderModel() {
							if (scope.hasModel) {
								$timeout(function () {
									if (options.modelType == 'date')
										ngModel.$setViewValue(scope.currentDate.clone().toDate());
									else {
										ngModel.$setViewValue(scope.currentDate.format(scope.format));
									}
									ngModel.$commitViewValue();
								}, 0)
							}
						}
						function buildScope() {
							angular.forEach(['onDateChange', 'onTimeChange', 'onChange'], function (key) {
								if (angular.isDefined(options[key]) && !angular.isFunction(options[key]))
									options[key] = $parse(options[key]);
							})
							if (ngModel) {
								scope.hasModel = true;
								var oldRender = ngModel.$render;
								ngModel.$render = function (value) {
									if (options.modelType == 'date') {
										var val = scope.currentDate.format(scope.format)
										if (element[0].tagName.toLowerCase() === 'input') {
											element.val(val);
										} else
											element.html(val);
									} else {
										oldRender();
									}
								};

								scope.$parent.$watch(attr.ngModel, function (newValue, oldValue) {
									if (newValue) {

										apply(function () {
											var dt;
											if (angular.isDate(newValue)) {
												options.modelType = 'date';
												dt = moment(newValue)
											} else
												dt = angular.isString(newValue) ? moment(newValue, scope.format) : moment.isMoment(newValue) ? newValue : moment();

											if (!dt.isValid())
												throw 'Type Error: ' + attr.ngModel + ' is not a valid Date, moment or date string...';
											if (options.timepicker) {
												var hr = dt.hour()
												if (hr < options.minHour)
													dt.hour(options.minHour)
												if (hr > options.maxHour)
													dt.hour(options.maxHour).minute(0)
											}
											scope.currentDate = dt.clone();
											scope.selectedDay = scope.currentDate.month() + '-' + scope.currentDate.date();
											if (!scope.modelSetted) {
												scope.modelSetted = true;
												fireChange()
												buildNew()
											}
											ngModel.$render();
											scope.modelDate = scope.currentDate.clone().toDate();
											if (options.autoHide && !options.timepicker)
												$picker.hide();
										});

									}
								})
							}

							if (options.minDateFrom) {
								var fromEl = angular.element(options.minDateFrom)
								if (fromEl.length) {
									var hasChage = false;
									var fromPicker = fromEl.data('$datepicker');
									var fromScope = fromPicker && fromPicker.$scope;
									fromScope && fromScope.$watch('modelDate', function (newValue, oldValue) {
										if (newValue) {
											apply(function () {
												var dt = moment(newValue);
												scope.minDate = dt.clone().add(options.minRange, options.rangeType);
												scope.currentDate = dt.clone().add(options.defaultRange, options.rangeTypee);
												scope.selectedDay = scope.currentDate.month() + '-' + scope.currentDate.date();
												$picker.caches = {};
												options.minYear = scope.minDate.year();
												if (options.maxRange) {
													scope.maxDate = dt.clone().add(options.maxRange, options.rangeType);
													options.maxYear = scope.maxDate.year();
												}
												getYearArray()
												buildNew();
												fireChange();
												hasChage = true;
											})
										}

									})
									fromScope && fromScope.$on(options.prefixEvent + '.hide', function () {
										if (hasChage)
											$picker.show();
										hasChage = false;
									});
								}
							}
							if (options.iconId) {
								var iconEl = angular.element(options.iconId)
								if (iconEl.length) {
									iconEl.on('click', function () {
										$picker.toggle();
									})
									scope.$on('$destroy', function () {
										iconEl.off('click')
									});
								}
							}
							scope.$watch('selectedIndex', function (newValue, oldValue) {

								if (newValue != oldValue) {
									var idx = newValue;
									if (idx >= scope.dayArray.length)
										idx = scope.dayArray.length - 1;
									var dt = scope.dayArray[idx];
									scope.selectedDay = dt.month + '-' + dt.day;
									var diff = dt.month - scope.currentDate.month();
									if (diff != 0) {
										if (diff > 0 && diff != 11 || diff == -11)
											$picker.next();
										else if (diff < 0 || diff == 11)
											$picker.before();
									}

									scope.currentDate.date(dt.day);
									scope.currentDate.month(dt.month);
									fireChange('date');
									renderModel();
								}
							})

							scope.$watch('currentDateObject.month', function (newval, oldval) {
								if (newval != oldval && oldval) {
									scope.selectedDay = scope.selectedDay.replace(oldval + '-', newval + '-');
								}
							})
							scope.$on('pickerTimeChanged', function (evt, val) {
								formatPicker();
								if (angular.isFunction(options.onTimeChange))
									options.onTimeChange(scope, { $currentDate: scope.currentDate.toDate() });
								if (angular.isFunction(options.onChange))
									options.onChange(scope, { $currentDate: scope.currentDate.toDate() });
							})
							scope.$on('pickerDatetimeChanged', function (evt, val) {
								formatPicker();
								if (angular.isFunction(options.onChange))
									options.onChange(scope, { $currentDate: scope.currentDate.toDate() });
							})
							scope.$on('pickerDateChanged', function (evt, val) {
								formatPicker();
								if (angular.isFunction(options.onDateChange))
									options.onDateChange(scope, { $currentDate: scope.currentDate.toDate() });
								if (angular.isFunction(options.onChange))
									options.onChange(scope, { $currentDate: scope.currentDate.toDate() });
							})
						}
						function formatPicker() {
							(options.timeView == 'list') && scrollTime();
							scope.currentMonthTitle = scope.currentDate.format(options.headerFormat);
							scope.currentYear = scope.currentDate.year();
							options.showYears && scrollYear();
						}
						function apply(fn) {
							if (!scope.$$phase) {
								scope.$apply(function () {
									fn();
								})
							}
							else
								fn();
						}

						return $picker;
					}
					return Factory;
				}
			];
		})
		.directive('timePickerSwitch',
		function () {
			return {
				restrict: 'AC',
				link: function postLink(scope, element, attr, transclusion) {
					var span = angular.element('<a href="#" class="tps-btn"></a>').append('<i class="' + scope.$eval(attr.timeIcon) + '"></i>').appendTo(element)
					var time = angular.element('<span>Time</span>').appendTo(span)
					scope.$on('pickerTimeChanged', function (evt, val) {
						var format = scope.$options.timeView == 'list' ? 'HH:mm' : 'HH:mm:ss';
						time.html(scope.currentDate.format(format))
					})
					element.on('click', function (evt) {
						evt.preventDefault();
						evt.stopPropagation();
						if (scope.$options.datepicker)
							scope.$toggleTimepicker();
						else
							scope.$apply(function () { scope.$hide() });

					});
					if (!scope.$options.datepicker)
						scope.$$postDigest(function () {
							scope.$toggleTimepicker();
						});

					element.append('<a class="tp-close" title="Close"><i class="' + scope.$eval(attr.closeIcon) + '"></i></a>');
					scope.$on('$destroy', function () {
						element.off('click')
					});

				}
			};
		})
		.directive('tpBindTime',
		function () {
			return {
				restrict: 'AC',
				link: function postLink(scope, element, attr, transclusion) {
					var type = attr.tpBindTime;
					scope.$watch('currentDateObject.' + type, function (newVal, oldVal) {
						switch (type) {
							case 'hour':
								element.html(scope.currentDate.format('HH'))
								break;
							case 'minute':
								element.html(scope.currentDate.format('mm'))
								break;
							case 'second':
								element.html(scope.currentDate.format('ss'))
								break;
						}
					})
				}
			};
		})
		.directive('tpTimeListItem',
		function () {
			return {
				restrict: 'AC',
				link: function postLink(scope, element, attr, transclusion) {
					var time = scope.time;
					element.html('<span>' + time + '</span>');
					element.on('click', function (evt) {
						scope.$parent.$apply(function () {
							scope.$parent.currentTimeString = time;
							scope.$parent.$setTime(time);
						})
					})
					scope.$on('$destroy', function () {
						element.off('click')
					});
				}
			};
		})
		.directive('calDateItem',
		function () {
			return {
				restrict: 'AC',
				link: function postLink(scope, element, attr, transclusion) {
					var index = parseInt(attr.calDateItem);
					var options = scope.$options;
					if (!element.hasClass('unselectable'))
						element.on('click', function (evt) {
							evt.preventDefault();
							scope.$parent.$apply(function () {
								if (scope.selectedIndex != index)
									scope.selectedIndex = index;
								else
									scope.$hide();
							});
						})
					scope.$on('$destroy', function () {
						element.off('click')
					});

				}
			};
		}
		)
		.directive('nqDatepicker', ['$datepicker',
			function ($datepicker) {
				return {
					restrict: 'EAC',
					require: '?ngModel',
					link: function postLink(scope, element, attr, ngModel) {
						var options = {
							$scope: scope.$new()
						}
						if (angular.isDefined(attr.qoMode)) {
							var mode = attr.qoMode;
							if (/datetime|time/.test(mode)) {
								options.timepicker = true;
								if (!attr.qoFormat) {
									if (mode == 'datetime')
										options.format = 'MM-DD-YYYY HH:mm:ss';
									else {
										options.format = 'HH:mm:ss';
										options.datepicker = false;
									}

								}
								else if (mode == 'time') {
									options.datepicker = false;
								}
							}
						}
						var picker = new $datepicker(element, options, attr, ngModel);
						element.data('$datepicker', picker)
						scope.$on('$destroy', function () {
							picker && picker.destroy();
							options = null;
							picker = null;
						});

					}
				};
			}
		])
}(window, window.angular);


'use strict';
angular.module('ngQuantum.dropdown', ['ngQuantum.popMaster'])
	.run(['$templateCache', function ($templateCache) {
		'use strict';

		$templateCache.put('dropdown/dropdown.tpl.html',
			"<ul tabindex=\"-1\" class=\"dropdown-menu\" role=\"menu\"><li role=\"presentation\" ng-class=\"{divider: item.divider}\" ng-repeat=\"item in content\"><a role=\"menuitem\" tabindex=\"-1\" ng-href=\"{{item.href}}\" ng-if=\"!item.divider && item.href\" ng-bind=\"item.text\"></a> <a role=\"menuitem\" tabindex=\"-1\" href=\"javascript:void(0)\" ng-if=\"!item.divider && item.click\" ng-click=\"$parent.$eval(item.click);$hide();\" ng-bind=\"item.text\"></a></li></ul>"
		);

	}])
	.provider('$dropdown', function () {
		var defaults = this.defaults = {
			effect: 'flip-x',
			typeClass: 'dropdown',
			prefixEvent: 'dropdown',
			placement: 'bottom-left',
			template: 'dropdown/dropdown.tpl.html',
			trigger: 'click',
			directive: 'nqDropdown',
			instanceName: 'dropdown',
			ensurePlacement: true,
			showArrow: false,
			fireEmit: true,
			displayReflow: false,
			keyboard: true,
			fixWidth: true
		};
		this.$get = [
			'$timeout',
			'$rootScope',
			'$popMaster', '$helpers',
			function ($timeout, $rootScope, $popMaster, $helpers) {

				function DropdownFactory(element, config, attr) {
					var $dropdown = {};
					config = angular.extend(config, $helpers.parseOptions(attr, config))
					var options = angular.extend({}, defaults, config);
					if (!options.independent) {
						var target;
						if (options.target)
							target = angular.element(options.target);
						else {
							target = angular.element(element.find('.dropdown-container, .dropdown-menu')[0]);
							if (target.length < 1)
								target = angular.element(element.next('.dropdown-container, .dropdown-menu')[0]);
						}

						if (target.length > 0)
							options.targetElement = target
					}

					$dropdown = new $popMaster(element, options);
					options = $dropdown.$options = $helpers.observeOptions(attr, $dropdown.$options);
					var scope = $dropdown.$scope
					$dropdown.$onKeyDown = function (e) {
						if (!/(38|40|13)/.test(e.keyCode))
							return;
						e.preventDefault();
						e.stopPropagation();

						var $items = $dropdown.$target.find('[role="menuitem"]:visible');
						$dropdown.$target.focus();
						if (!$items.length) return;
						var index = scope.lastIndex > -1 ? scope.lastIndex : -1
						if (e.keyCode == 38 && index > 0) index--                  // up
						if (e.keyCode == 40 && index < $items.length - 1) index++  // down
						if (!~index) index = 0
						if (e.keyCode === 13) {
							return angular.element($items[index]).trigger('click');
						}
						$items.eq(index).focus()
						scope.lastIndex = index;

					};
					var show = $dropdown.show;
					$dropdown.show = function (callback) {
						var promise = show(callback);
						angular.element(document).off('keydown.nqDropdown.api.data');
						angular.element(document).on('keydown.nqDropdown.api.data', $dropdown.$onKeyDown);

						if (!scope.$$phase) {
							scope.$apply(function () {
								$dropdown.$target.focus();
							})
						}
						else
							$dropdown.$target.focus();
						if (!options.independent && options.fixWidth) {
							var ew = element.outerWidth(true), tw = $dropdown.$target.outerWidth(true);
							if (ew > tw)
								$dropdown.$target.css('min-width', ew)
						}
						element.parent().addClass('open')
						return promise;
					};
					var hide = $dropdown.hide;
					$dropdown.hide = function (callback) {
						scope.lastIndex = -1;
						angular.element(document).off('keydown.nqDropdown.api.data');
						element.parent().removeClass('open')
						return hide(callback);
					};
					if (attr && angular.isDefined(options.directive)) {
						attr[options.directive] && options.$scope.$watch(attr[options.directive], function (newValue, oldValue) {
							scope.content = newValue;
						}, true);
					}


					if (options.autoDestroy)
						scope.$on('$destroy', function () {
							$dropdown && $dropdown.destroy();
							$dropdown = null

						})
					return $dropdown;
				}
				return DropdownFactory;
			}
		];
	})
	.directive('nqDropdown', ['$dropdown', 'templateHelper',
		function ($dropdown, templateHelper) {
			return {
				restrict: 'EA',
				link: function postLink(scope, element, attr, transclusion) {
					var options = {
						$scope: scope.$new()
					};

					options.uniqueId = attr.qoUniqueId || attr.id || options.$scope.$id;
					if (attr.qoTrigger && attr.qoTrigger.indexOf('hover') > -1) {
						options.holdHoverDelta = true;
						options.delayHide = 100;
						options.delayShow = 10;
					}

					var dropdown = {};
					if (angular.isDefined(attr.qoIndependent)) {
						options.independent = true;
						options.html = true;
						options.displayReflow = false;
						options.targetElement = element;
						options.fireEmit = true;
						dropdown = new $dropdown(null, options, attr);

					}
					else
						dropdown = new $dropdown(element, options, attr);

					scope.$on('$destroy', function () {
						dropdown = null;
					})
					element.data('$nqDropdown', dropdown)

				}
			};
		}
	])

'use strict';
angular.module('ngQuantum.loading', ['ngQuantum.services.lazy'])
	.run(['$http', '$rootScope', '$timeout', function ($http, $rootScope, $timeout) {
		$rootScope.$watch(function () { return $http.pendingRequests.length }, function (newVal, oldVal) {
			$rootScope.$pendingRequestCount = $rootScope.$pendingRequestCount || 0;
			$timeout(function () {
				$rootScope.$pendingRequestCount = $rootScope.$pendingRequestCount + (newVal - oldVal);
			}, 0)
		})

	}])
	.provider('$loading', function () {
		var defaults = this.defaults = {
			placement: 'top',
			container: 'body',
			backdrop: false,
			timeout: 2000,
			delayHide: 500,
			theme: false,
			showBar: true,
			showSpinner: true,
			spinnerIcon: '<i class="fic spin-icon fu-spinner-fan spin"></i>',
			busyText: 'Loading...'
		};
		this.$get = ['$timeout', '$rootScope', '$compile', '$http',
			function ($timeout, $rootScope, $compile, $http) {
				function LoadingFactory(config, theme, placement) {
					var $loading = {};
					if (angular.isString(config)) {
						config = {
							busyText: config,
							theme: theme,
							placement: placement
						}
					}
					var options = $loading.$options = angular.extend({}, defaults, config);
					var container = angular.isElement(options.container) ? options.container : angular.element(options.container)
					if (!container.length)
						container = angular.element('body');
					var scope = $loading.$scope = options.$scope || $rootScope.$new(), cancel;

					var template = angular.element(getTemplate());
					var place = options.container == 'body' ? 'prepend' : 'append';
					$compile(template)(scope);
					$timeout(function () {
						container[place](template);
					}, 0)

					scope.busyText = options.busyText;
					if (options.theme) {
						scope.loadingTheme = 'loading-' + options.theme;
						scope.progressTheme = 'progress-bar-' + options.theme;
					}
					scope.showBar = options.showBar;
					scope.showSpinner = options.showSpinner;
					scope.currentRate = 0;
					if (options.placement)
						template.addClass('loading-' + options.placement)
					$loading.show = function () {
						template.css('display', 'block')
						$loading.isShown = true;
						if (options.showBar)
							$timeout(function () {
								scope.currentRate = 0;
								$loading.updateProgress();
							}, 0)

						options.timeout !== false &&
							$timeout(function () {
								$loading.hide();
							}, options.timeout)
					};
					$loading.hide = function () {
						if (!$loading.isShown)
							return;
						scope.currentRate = 100;
						$timeout(function () {
							template.css('display', 'none')
							scope.currentRate = 0;
							$loading.isShown = false;
						}, options.delayHide)

					};
					$loading.updateProgress = function (rate) {
						if (!$loading.isShown || $http.$pendingRequestCount > 0)
							return;
						if (rate)
							scope.currentRate = rate;
						else {
							if (scope.currentRate < 100)
								scope.currentRate = scope.currentRate + (scope.currentRate < 80 ? 5 : (parseInt(100 - scope.currentRate) / 2));
							$timeout(function () {
								if (scope.currentRate < 99)
									$loading.updateProgress();
							}, 20)
						}
					};
					scope.$on('$destroy', function () {
						$loading = null;
					});
					$rootScope.$watch('$pendingRequestCount', function (newVal, oldVal) {
						if (newVal <= 0) {
							$http.$pendingRequestCount = 0;
							$timeout(function () {
								$loading.hide();
							}, 10)
						}
						else {
						}

					})
					function getTemplate() {
						var html = '<div class="loading-container"  ng-class="loadingTheme">'
							+ '<div class="progress" ng-show="showBar">'
							+ '<div class="progress-bar active" ng-class="progressTheme" role="progressbar" ng-style="{\'width\':currentRate + \'%\'}" aria-valuenow="{{currentRate}}" aria-valuemin="0" aria-valuemax="100">'
							+ '</div>'
							+ '</div>'
							+ '<div class="spinner-container">'
							+ '<div class="busy-text">' + options.spinnerIcon + ' {{busyText}}</div>'
							+ '</div>'
							+ '</div>'
							+ ''
							+ '';
						return html;
					}
					return $loading;
				}
				return LoadingFactory;
			}
		];
	})
'use strict';
angular.module('ngQuantum.loadingButton', ['ngQuantum.services.helpers'])
	.provider('$loadingButton', function () {
		var defaults = this.defaults = {
			timeout: 2000,
			onError: angular.noop,
			onSuccess: angular.noop,
			loadingText: 'Loading...',
			showIcons: true,
			spinner: '<i class="fic fu-spinner-circle spin"></i> ',
			successIcon: '<i class="fic fu-check  flash"></i>',
			errorIcon: '<i class="fic fu-cross-c flash red"></i> ',
			timeoutIcon: '<i class="fic fu-bell-off"></i> '
		};
		this.$get = function () {
			return { defaults: defaults };
		};
	})
	.directive("nqLoadingButton", ['$parse', '$loadingButton', '$helpers', '$timeout', '$q',
		function ($parse, $loadingButton, $helpers, $timeout, $q) {
			return {
				restrict: 'A',
				link: function (scope, element, attr) {
					var fn = $parse(attr.nqLoadingButton);
					var options = angular.extend({}, $loadingButton.defaults);
					angular.forEach(['onSuccess', 'onTimeout', 'onError'], function (key) {
						if (angular.isDefined(attr[key]))
							options[key] = $parse(attr[key]);
					})
					angular.forEach(['loadingText', 'showIcons', 'timeout'], function (key) {
						angular.isDefined(attr[key]) && (options[key] = $helpers.parseConstant(attr[key]));
					})
					var cloneElement = element.clone();
					cloneElement.attr('disabled', 'disabled').html(options.loadingText);

					options.showIcons && cloneElement.prepend(options.spinner);
					var erricon, timeicon, successicon;
					if (options.showIcons) {
						successicon = angular.isElement(options.successIcon) ? options.successIcon : angular.element(options.successIcon)
						erricon = angular.isElement(options.errorIcon) ? options.errorIcon : angular.element(options.errorIcon)
					}
					element.on('click', function (event) {
						scope.$apply(function () {
							getTimer(event);
						});
					});

					function getTimer(event) {
						element.css('display', 'none');
						element.after(cloneElement);
						$q.when(fn(scope, { $event: event }))
							.then(function (res) {
								element.css('display', '');
								cloneElement.remove();
								successicon && element.prepend(successicon);
								successicon && setTimeout(function () {
									successicon.remove();
								}, options.timeout)
								options.onSuccess(scope, { $event: event, $data: res });
								return res;
							}, function (res) {
								element.css('display', '');
								cloneElement.remove();
								erricon && element.prepend(erricon);
								options.onError(scope, { $event: event, $data: res });
								erricon && setTimeout(function () {
									erricon.remove();
								}, options.timeout)
							});
					}
				}
			}
		}]);
'use strict';
angular.module('ngQuantum.modal', ['ngQuantum.popMaster'])
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('modal/modal.tpl.html',
			'<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body"  ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">{{closeText}}</button></div><button type="button" class="close" ng-click="$hide()" ng-bind-html="closeIcon">&nbsp;</button></div></div></div>'
		);
		$templateCache.put('modalbox/alertbox.tpl.html',
			'<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body"><div class="modal-body-inner" ng-bind="content"></div></div><div class="modal-footer"><button type="button" class="btn btn-primary" ng-click="$hide()">{{okText}}</button></div><button type="button" class="close" ng-click="$hide()" ng-bind-html="closeIcon">&nbsp;</button></div></div></div>'
		);
		$templateCache.put('modalbox/confirmbox.tpl.html',
			'<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body"><div class="modal-body-inner" ng-bind="content"></div></div><div class="modal-footer"><button type="button" class="btn btn-primary" ng-click="$cancel()">{{cancelText}}</button> <button type="button" class="btn btn-success" ng-click="$confirm()">{{confirmText}}</button></div><button type="button" class="close" ng-click="$cancel()" ng-bind-html="closeIcon">&nbsp;</button></div></div></div>'
		);
		$templateCache.put('modalbox/promptbox.tpl.html',
			'<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body"><div class="modal-body-inner" ng-bind="content"></div><div class="margin-t form-group"><label for="promptModel">{{promptLabel}}</label><input type="text" class="form-control" name="promptModel" ng-model="promptModel"></div></div><div class="modal-footer"><button type="button" class="btn btn-primary" ng-click="$cancel()">{{cancelText}}</button> <button type="button" class="btn btn-success" ng-click="$confirm()">{{confirmText}}</button></div><button type="button" class="close" ng-click="$cancel()" ng-bind-html="closeIcon">&nbsp;</button></div></div></div>'
		);
	}])
	.provider('$modal', function () {
		var defaults = this.defaults = {
			effect: 'from-top',
			backdropEffect: 'fade-in',
			animateTarget: '.modal-dialog',
			typeClass: 'modal',
			prefixEvent: 'modal',
			directive: 'nqModal',
			placement: 'near-top',
			uniqueId: 'nq-modal',
			trigger: 'click',
			clearExists: false,
			template: 'modal/modal.tpl.html',
			contentTemplate: false,
			container: false,
			element: null,
			backdrop: true,
			keyboard: true,
			closeText: 'Close',
			closeIcon: '<i class="fic fu-cross"></i>',
			buildOnShow: true,
			html: false,
			size: false,
			displayReflow: false,
			show: false,
			autoDestroy: false
		};
		this.$get = ['$window', '$compile', '$http', '$sce', '$timeout', '$helpers', '$popMaster',
			function ($window, $compile, $http, $sce, $timeout, $helpers, $popMaster) {
				var $animate = $helpers.injectModule('$animate', 'ngAnimate');
				var forEach = angular.forEach;
				var bodyElement = angular.element($window.document.body);
				function ModalFactory(config, attr) {

					var $modal = {}, element = config.element;
					if (!config.$scope) {
						config.autoDestroy = true;
						config.show = true;
						config.html = true;
						config.fireEmit = true;
					}
					if (attr)
						config = $helpers.parseOptions(attr, config);
					var options = config = angular.extend({}, defaults, config);



					options.container = 'body';
					options.preventReplace = true;
					$modal = new $popMaster(element, options);
					if (attr)
						options = $modal.$options = $helpers.observeOptions(attr, $modal.$options);
					else
						options = $modal.$options;

					var scope = $modal.$scope
					config.content && (scope.content = config.content)
					config.title && (scope.title = config.title)
					scope.closeText = options.closeText;
					scope.closeIcon = options.closeIcon;

					var backdropElement = angular.element('<div class="' + options.typeClass + '-backdrop"/>');

					var init = $modal.init;
					$modal.init = function () {
						init();
						$modal.$promise.then(function (contentTemplate) {
							if (options.backdrop) {
								backdropElement.prependTo($modal.$target)
							}
							if (options.screenMode) {
								$modal.$target.addClass('screen-mode')
							}
							else if ($modal.$animateTarget && options.size)
								$modal.$animateTarget.addClass('modal-' + options.size)

							$modal.footerCheck(contentTemplate);
							headerCheck(contentTemplate);
							if (options.trigger == 'hover') {
								element.off('mouseleave', $modal.leave);
							}
						})

					};
					var destroy = $modal.destroy;
					$modal.destroy = function () {
						destroy();
						if (backdropElement) {
							backdropElement.off('click')
							backdropElement.remove();
							backdropElement = null;
						}
					};
					var show = $modal.show;
					$modal.show = function () {
						var promise = show();
						if (options.backdrop) {
							if (options.backdropEffect) {
								backdropElement.addClass('in');
								backdropElement.show();
							}
							options.backdrop !== 'static' && backdropElement.on('click', hideOnBackdropClick);
						}
						if (options.trigger == 'hover') {
							$helpers.unBindTriggers(element, 'hover', $modal)
						}
						if ($modal.$animateTarget && options.size)
							$modal.$animateTarget.addClass('modal-' + options.size);

						setTimeout(function () {
							resizeModal();
						}, 0);
						return promise;
					};
					var hide = $modal.hide;
					$modal.hide = function () {
						if (options.backdrop) {
							if (options.backdropEffect) {
								backdropElement.addClass('fade')
								backdropElement.removeClass('in')


							}
							options.backdrop !== 'static' && backdropElement && backdropElement.off('click');

						}
						if (options.trigger == 'hover' && element) {
							$helpers.bindTriggers(element, 'hover', $modal)
						}
						var promise = hide();
						promise.then(function () {
							if ($modal.$animateTarget && options.size)
								$modal.$animateTarget.removeClass('modal-' + options.size);

							clearHeight();
							options.autoDestroy && $modal && $modal.destroy();
						});
						return promise;

					};
					function hideOnBackdropClick(evt) {
						options.backdrop === 'static' ? $modal.focus() : $modal.hide();
					}
					$modal.footerCheck = footerCheck;
					function footerCheck(contentTemplate) {
						var customFooter = $modal.$target.find('.custom-footer');
						if (!customFooter.length && options.htmlObject)
							customFooter = scope.content.find('.custom-footer');
						if (!customFooter.length && contentTemplate && contentTemplate.find)
							customFooter = contentTemplate.find('.custom-footer');
						var footer = $modal.$target.find('.modal-footer');
						if (customFooter.length && footer.length) {
							footer.replaceWith(customFooter.addClass('modal-footer'))
							$modal.customFooter = customFooter;
						}
					};
					function headerCheck(contentTemplate) {
						var customHeader = $modal.$target.find('.custom-header');
						if (!customHeader.length && options.htmlObject)
							customHeader = scope.content.find('.custom-header');
						if (!customHeader.length && contentTemplate && contentTemplate.find)
							customHeader = contentTemplate.find('.custom-header');
						var header = $modal.$target.find('.modal-header');
						if (customHeader.length && header.length) {
							scope.title = true;
							header.replaceWith(customHeader.addClass('modal-header'))
						}
					};
					if (attr) {
						angular.forEach(['title', 'content'], function (key) {
							var akey = 'qs' + key.capitaliseFirstLetter();
							attr[akey] && (scope[key] = $sce.trustAsHtml(attr[akey]));
							attr.$$observers && attr.$$observers[akey] && attr.$observe(akey, function (newValue, oldValue) {
								scope[key] = $sce.trustAsHtml(newValue);
							});
						});
						if (angular.isDefined(options.directive)) {
							attr[options.directive] && options.$scope.$watch(attr[options.directive], function (newValue, oldValue) {
								if (angular.isObject(newValue)) {
									if (angular.isArray(newValue))
										scope.content = newValue;
									else
										angular.extend(scope, newValue);
								} else {
									scope.content = newValue;
								}
							}, true);
						}

					}


					function resizeModal() {
						if (!$modal.$target) {
							setTimeout(function () {
								resizeModal();
							}, 10);
							return false;
						}
						var cnt = $modal.$target.find('.modal-content'),
							bdy = $modal.$target.find('.modal-body'),
							hdr = $modal.$target.find('.modal-header'),
							ftr = $modal.$target.find('.modal-footer'),
							dialog = $modal.$target.find('.modal-dialog');
						if (options.screenMode) {
							fixBodyHeight(cnt, hdr, ftr);
						}
						else {
							var mh = $modal.$target.innerHeight(),
								dh = dialog.outerHeight(true);
							if (dh > mh) {
								$modal.$target.addClass('modal-fix-height');
								fixBodyHeight(cnt, hdr, ftr);
							} else {
								verticalPlacement(dialog, mh - dialog.innerHeight())
							}
						}
					}
					function fixBodyHeight(cnt, hdr, ftr) {
						var hh = hdr.length ? hdr.outerHeight(true) : 0,
							fh = ftr.length ? ftr.outerHeight(true) : 0;
						cnt.css({ 'padding-top': hh, 'padding-bottom': fh });
						hdr.css('margin-top', -hh);
					}
					function clearHeight() {
						$modal.$target.removeClass('modal-fix-height');
						$modal.$target.find('.modal-content').css({ 'padding-top': '', 'padding-bottom': '' });
						$modal.$target.find('.modal-header').css('margin-top', '');
						$modal.$target.find('.modal-dialog').css('top', '');
					}
					function verticalPlacement(dialog, diff) {
						if (diff > 0) {
							var top = 0;
							switch (options.placement) {
								case 'center':
									top = diff / 2
									break;
								case 'bottom':
									top = diff
									break;
								case 'near-top':
									top = diff / 3
									break;
								case 'near-bottom':
									top = (diff / 3) * 2
									break;
								default:
									top = 0
							}
							dialog.css('top', top);
						}
					}
					scope.$on('$destroy', function () {
						$modal && !$modal.isDestroyed && $modal.destroy();
						$modal = null;
					});
					return $modal;
				}
				return ModalFactory;
			}
		];
	})
	.directive('nqModal', ['$modal',
		function ($modal) {
			return {
				restrict: 'EAC',
				scope: true,
				link: function postLink(scope, element, attr, transclusion) {
					var options = {
						$scope: scope
					};
					options.uniqueId = attr.qoUniqueId || attr.id || scope.$id;
					var modal = {}
					if (angular.isDefined(attr.qoIndependent)) {
						options.htmlObject = true;
						scope.content = element;
						options.buildOnShow = false;
						modal = $modal(options, attr);
					}
					else {
						options.element = element;
						options.html = true;
						modal = $modal(options, attr);

					}
					element.data('$nqModal', modal)
				}
			};
		}
	])
	.directive('modalBodyInner', function () {
		return {
			restrict: 'C',
			require: '?nqModal',
			link: function postLink(scope, element, attr, controller) {
				element.on('scroll', function (e) {
					scope.$broadcast('staticContentScroll', this.scrollTop)
				})
			}
		};
	})

'use strict';
angular.module('ngQuantum.modalBox', ['ngQuantum.modal'])
	.provider('$modalBox', function () {
		var defaults = this.defaults = {
			effect: 'slit',
			boxType: 'alert',
			typeClass: 'modalbox',
			instanceName: 'modal',
			prefixEvent: 'modalbox',
			directive: 'nqModalBox',
			placement: 'near-top',
			uniqueId: 'nq-modalbox',
			trigger: 'click',
			okText: 'OK',
			cancelText: 'Cancel',
			confirmText: 'Confirm',
			template: false,
			showIcon: true,
			promptModel: '$promptValue',
			alertTemplate: 'modalbox/alertbox.tpl.html',
			confirmTemplate: 'modalbox/confirmbox.tpl.html',
			promptTemplate: 'modalbox/promptbox.tpl.html'
		};
		this.$get = ['$modal', '$parse', '$helpers',
			function ($modal, $parse, $helpers) {
				function ModalBoxFactory(config, attr) {
					findTemplate()
					var $modalBox = {}, element = config.element, $buttons;

					var options = angular.extend({}, defaults, config);
					attr && angular.forEach(['afterOk', 'afterConfirm', 'afterCancel', 'afterCustom'], function (key) {
						if (angular.isDefined(attr[key])) {
							options[key] = $parse(attr[key]);
						}
					})
					$modalBox = new $modal(options, attr);
					options = config = $modalBox.$options;
					var scope = $modalBox.$scope
					angular.forEach(['okText', 'cancelText', 'confirmText', 'promptLabel'], function (key) {
						scope[key] = options[key]

					})
					var init = $modalBox.init;
					$modalBox.init = function () {
						init();
						if (!options.showIcon) {
							$modalBox.$target.addClass('no-icon')
						}
					};
					var show = $modalBox.show;
					$modalBox.show = function () {
						if (options.boxType == 'prompt')
							scope.promptModel = '';
						var promise = show();
						if ($buttons)
							$buttons.on('click', $modalBox.hide);
						return promise;
					};
					var hide = $modalBox.hide;
					$modalBox.hide = function () {

						if (angular.isFunction(options.afterOk) && !$buttons) {
							options.afterOk(scope)
						}
						if ($buttons) {
							if (angular.isFunction(options.afterCustom))
								options.afterCustom(scope)
							$buttons.off('click', $modalBox.hide)
						}
						return hide();
					};
					var footerCheck = $modalBox.footerCheck;
					$modalBox.footerCheck = function () {
						footerCheck(arguments);
						if ($modalBox.customFooter && $modalBox.customFooter.length)
							$buttons = $modalBox.customFooter.find('button');
					};
					scope.$confirm = function () {
						scope.$$postDigest(function () {
							$modalBox.hide();
							if (angular.isFunction(options.afterConfirm)) {
								scope.$parent.$apply(function () {
									if (options.boxType == 'prompt')
										scope.$parent[options.promptModel] = scope.promptModel;
								})
								options.afterConfirm(scope);
							}
						});

					}
					scope.$cancel = function () {
						scope.$$postDigest(function () {
							$modalBox.hide();
							if (angular.isFunction(options.afterCancel)) {
								options.afterCancel(scope)
							}
						});

					}
					scope.$on('$destroy', function () {
						$modalBox && !$modalBox.isDestroyed && $modalBox.destroy();
						$modalBox = null;
					});
					function findTemplate() {

						switch (config.boxType) {
							case 'alert':
								config.template = config.alertTemplate || defaults.alertTemplate
								break;
							case 'confirm':
								config.template = config.confirmTemplate || defaults.confirmTemplate
								break;
							case 'prompt':
								config.template = config.promptTemplate || defaults.promptTemplate
								break;
							default:
								config.template = config.template || defaults.alertTemplate
								break;
						}
					}
					return $modalBox;
				}
				return ModalBoxFactory;
			}
		];
	})
	.directive('nqModalBox', ['$modalBox', '$helpers',
		function ($modalBox, $helpers) {
			return {
				restrict: 'EAC',
				scope: true,
				link: function postLink(scope, element, attr, transclusion) {
					var options = {
						$scope: scope
					};
					angular.forEach(['boxType', 'promptLabel', 'promptModel', 'alertTemplate', 'confirmTemplate', 'promptTemplate',
						'showIcon', 'okText', 'cancelText', 'confirmText'], function (key) {
							if (angular.isDefined(attr[key]))
								options[key] = $helpers.parseConstant(attr[key]);

						})
					options.uniqueId = attr.uniqueId || attr.id || scope.$id;
					options.element = element;
					var modalBox = {}
					if (angular.isDefined(attr.contentTarget)) {
						var content = angular.element(attr.contentTarget)
						if (!content.length) {
							content = angular.element('<span><span class="label label-warning">Warning :</span> No content element find</span>')
						}
						options.htmlObject = true;
						options.buildOnShow = false;
						scope.content = content;
						modalBox = new $modalBox(options, attr);
					}
					else {
						options.element = element;
						options.html = true;
						modalBox = new $modalBox(options, attr);

					}
					scope.$on('$destroy', function () {
						modalBox = null;
					})
					element.data('$nqModalBox', modalBox)
				}
			};
		}
	])

	+ function (window, angular, undefined) {
		var props = ['placement', 'delayShow', 'delayHide', 'effect', 'speed', 'theme', 'showArrow', 'holdHoverDelta'];
		var app = angular.module('ngQuantum.popMaster', ['ngQuantum.services', 'ngQuantum.directives'])
			.provider('$popMaster', function () {
				var defaults = this.defaults = {
					effect: 'fade-in',
					speed: 'fastest',
					typeClass: 'pop',
					prefixEvent: 'pop',
					fireEmit: false,
					fireBroadcast: false,
					container: false,
					placement: 'top',
					offsetTop: 0,
					offsetLeft: 0,
					targetElement: false,
					template: angular.element('<div style="min-width:100px; padding:3px; border:1px; solid #aaa">You should prepare a content will replace here...</div>'),
					contentTemplate: false,
					trigger: 'hover focus',
					keyboard: false,
					html: false,
					show: false,
					clearExists: true,
					autoDestroy: true,
					displayReflow: true,
					theme: false,
					delayShow: 0,
					delayHide: 0

				}
				this.$get = ['$window', '$rootScope', '$compile', '$parse', '$http', '$timeout', '$animate', '$placement', '$helpers', 'templateHelper', '$q',
					function ($window, $rootScope, $compile, $parse, $http, $timeout, $animate, $placement, $helpers, templateHelper, $q) {
						var trim = String.prototype.trim;
						var isTouch = $helpers.isTouch();
						var htmlReplaceRegExp = /ng-bind="/gi;
						var $$rAF = $helpers.injectModule('$$rAF', 'ngAnimate');
						function MasterFactory(element, config) {
							var $master = {};
							var reopen = false;
							$master.$currentElement = undefined;
							var options = $master.$options = config = angular.extend({}, defaults, config);
							var lastplacement = options.placement;
							var scope = $master.$scope = options.$scope || $rootScope.$new();
							options.delayShow = $helpers.ensureNumber(options.delayShow),
								options.delayHide = $helpers.ensureNumber(options.delayHide);
							if (angular.isDefined(options.onShow) || angular.isDefined(options.onHide))
								options.fireBroadcast = options.fireEmit = true;
							if (!options.instanceName)
								options.instanceName = options.typeClass
							var originalOptions = $master.$originalOptions = angular.extend({}, options);
							isTouch && (options.keyboard = false);
							angular.forEach(['hide', 'show', 'toggle'], function (value) {
								scope['$' + value] = function () {
									scope.$$postDigest(function () {
										$master[value]();
									});
								}
							})
							$master.$isShown = scope.$isShown = false;
							var timeout, hoverState, linker, $target, $container, $animateTarget, shouldCompile;


							options.hasClick = false;
							$master.init = function () {
								if (element && options.trigger) {
									$helpers.unBindTriggers(element, options.trigger, $master);
									options.hasClick = $helpers.bindTriggers(element, options.trigger, $master);
								}
								if (!options.buildOnShow || options.show)
									build();
								if (options.show) {
									scope.$$postDigest(function () {
										options.trigger === 'focus' && element ? element.focus() : $master.show();
									});
								}

							}
							function start() {
								if (!options.buildOnShow || options.show) {
									if (options.targetElement) {
										$master.$promise = templateHelper.fetchContent(options.targetElement);
									}
									else {
										if (angular.isElement(options.template))
											$master.$promise = templateHelper.fetchContent(options.template);
										else if (options.template.indexOf('.html') > -1)
											$master.$promise = templateHelper.fetchTemplate(options.template);
										else
											$master.$promise = templateHelper.fetchContent(angular.element(options.template));
										shouldCompile = true;
									}
									if (options.contentTemplate) {
										$master.$promise = templateHelper.fetchContentTemplate($master)
										shouldCompile = true;
									}
									$master.$promise.then(function (template) {
										if (angular.isElement(template))
											linker = template;
										else {
											if (options.html)
												template = template.replace(htmlReplaceRegExp, 'ng-bind-html="');
											if (options.htmlObject)
												template = template.replace(/ng-bind="content"/gi, 'nq-bind="content"')
													.replace(/ng-bind-html="content"/gi, 'nq-bind="content"');
											linker = trim.apply(template);
										}
										options.buildOnShow = false;
										$master.init();
									});
								}
								else
									$master.$promise = $q.when($master.init());

								if (element && options.readonly)
									element.attr('readonly', true)
							}

							$master.destroy = function () {
								$master.isDestroyed = true;
								angular.element('body').off('click', onBodyClick);
								if (element && options.trigger)
									$helpers.unBindTriggers(element, options.trigger, $master);
								if ($target) {
									$target.off();
									$target.remove();
									$target = null;
								}
								!options.$scope && scope.$destroy();
							};
							$master.enter = function () {
								var promise;
								if (this !== $master)
									$master.$currentElement = angular.element(this);
								clearTimeout(timeout);
								hoverState = 'in';
								if (!options.delayShow) {
									return $master.show();
								}
								timeout = setTimeout(function () {
									if (hoverState === 'in')
										promise = $master.show();
								}, options.delayShow);
								return promise;
							};
							$master.show = function (callback) {
								var lasttheme;
								var promise;
								if (options.buildOnShow) {
									options.show = true;
									options.buildOnShow = false;
									start();
									return false;
								}
								options = $master.$options;
								if (($master.$isShown || $master.$isShowing || $master.$isHidding))
									return false;
								if (options.clearExists)
									$master.clearExists();
								element = $master.$currentElement || element;
								var modal;
								if (element)
									modal = element.closest('.modal');
								if (modal && modal.length)
									$container = modal;
								var parent = $container ? $container : null;

								var after = $container ? angular.element(parent[0].lastChild) : element;
								if (after && after.length < 1)
									after = null;
								if (!$target || $target.length < 1)
									build();
								else
									ensureFixedPlacement();
								if (options.theme) {
									$target.removeClass(lasttheme);
									lasttheme = options.instanceName + '-' + options.theme;
									$target.addClass(lasttheme);
								}

								if (angular.isFunction($master['beforeShow'])) {
									$master['beforeShow'](element, $target)
								}
								$target.removeClass(lastplacement);
								lastplacement = options.placement;
								$target.css({ display: 'block', top: '', left: '' }).addClass(lastplacement);
								$target.removeClass('with-arrow');

								$master.$isShowing = true;
								if (options.effect) {
									if (options.displayReflow) {
										$target.addClass(options.effect).addClass(options.speed);
										if (options.effect.indexOf('collapse') > -1)
											$target.height($target.outerHeight());

										promise = $animate.enter($target, parent, after).then(function () {
											complateShow(callback)
											$master.fireEvents('show');
											$master.$isShowing = false;
											$timeout(function () {
												$master.$isShown = scope.$isShown = true;
											}, 0)
										});
										$$rAF && $$rAF($master.$applyPlacement);


									}
									else {
										$animateTarget.removeClass('ng-animate').removeClass(options.speed).removeClass(options.effect + '-remove').removeClass(options.effect + '-remove-active');
										$master.$applyPlacement();
										$animateTarget.addClass(options.speed);
										if (options.effect.indexOf('collapse') > -1)
											$animateTarget.height($target.outerHeight());

										$animateTarget.css('display', 'block');
										$animateTarget && $animateTarget.css('visibility', "");
										$target && $target.css('display', 'block')
										promise = $animate.addClass($animateTarget, options.effect).then(function () {
											complateShow(callback);
											$master.fireEvents('show');
											$animateTarget.show();
											$master.$isShowing = false;
											$timeout(function () {
												$master.$isShown = scope.$isShown = true;
											}, 0)

										});
									}
								}
								else {
									$master.$applyPlacement();
									promise = $q.when(complateShow(callback))
									$master.fireEvents('show');
									$master.$isShowing = false;
									$master.$isShown = scope.$isShown = true;
								}


								scope.$$phase || scope.$digest();
								if (/dropdown|popover|datepicker|colorpicker/.test(options.instanceName))
									options.showArrow && $target.addClass('with-arrow')
								return promise;
							};
							$master.leave = function (evt) {
								var promise;
								if (this !== $master)
									$master.$currentElement = angular.element(this);
								clearTimeout(timeout);
								hoverState = 'out';
								var exrtadelay = options.delayHide || 0;
								if (evt && evt.type == 'mouseleave') {
									$master.$isShowing = false;
									!exrtadelay && (exrtadelay = 10);
								}
								timeout = setTimeout(function () {
									if (hoverState === 'out') {
										promise = $master.hide();
									}
								}, exrtadelay);
								return promise;
							};
							$master.hide = function (callback) {

								var promise;
								if (!$target)
									return false;

								if (!options.forceHide) {
									if (!$master.$isShown)
										return false;
									if ($master.$isShowing || $master.$isHidding)
										return false;
								}
								if ($master.beforeHide)
									$master.beforeHide();
								$master.$isHidding = true;
								element = $master.$currentElement && $master.$currentElement || element;
								if (options.effect) {
									if (options.displayReflow)
										promise = $animate.leave($target).then(function () {
											complateHide(callback);
											if (options.effect.indexOf('collapse') > -1)
												$target.css('height', '');
											$master.fireEvents('hide')
											$timeout(function () {
												$master.$isShown = scope.$isShown = false;
											}, 0)
										});
									else {
										$animateTarget.animationEnd(function (evt) {
											!$master.$isShowing && $animateTarget.hide();
										});
										$animateTarget && $animateTarget.css('visibility', "hidden");
										promise = $animate.removeClass($animateTarget, options.effect).then(function () {
											$animateTarget.hide();
											if ($target) {
												$target.hide();
												if (options.effect.indexOf('collapse') > -1)
													$animateTarget && $animateTarget.css('height', '');
												complateHide(callback);
												$master.fireEvents('hide');
												$timeout(function () {
													$master.$isShown = scope.$isShown = false;
												}, 0)

											}
										});
									}
								}
								else {
									if ($target) {
										$target.hide();
										promise = $q.when(complateHide(callback));
										$master.fireEvents('hide');
										$master.$isShown = scope.$isShown = false;
									}
								}

								scope.$$phase || scope.$digest();
								return promise;

							};
							$master.toggle = function (elem) {
								if (angular.isElement(elem))
									$master.$currentElement = elem;
								else if (this !== $master)
									$master.$currentElement = angular.element(this);

								$master.$isShown ? $master.leave() : $master.enter();
							};
							$master.focus = function () {
								$target && $target.focus();
							};
							$master.clearExists = function () {
								var exists = angular.element('.' + options.typeClass);
								angular.forEach(exists, function (key, value) {
									var sc = angular.element(key).scope();
									sc && (sc.$id != scope.$id) && sc.$isShown && sc.$hide();

								})
							};
							$master.$onKeyUp = function (evt) {
								evt.which === 27 && $master.hide();
							};
							$master.$onFocusKeyUp = function (evt) {
								evt.which === 27 && element.blur();
							};
							$master.$onFocusElementMouseDown = function (evt) {
								if (options.isInput)
									return true;
								evt.preventDefault();
								evt.stopPropagation();
								$master.$isShown ? element.blur() : element.focus();
							};
							$master.$applyPlacement = function () {
								if (options.inline)
									return;
								if ($container && options.container !== 'self')
									$target.appendTo($container)
								if (!options.preventReplace) {
									$placement.applyPlacement($master.$toElement && $master.$toElement || $master.$currentElement && $master.$currentElement || element, $target, options)
									$target && $target.css({ position: '' })
								}

							};
							$master.fireEvents = function (status) {
								if (options.fireEmit)
									scope.$emit(options.prefixEvent + '.' + status, $target);
								if (options.fireBroadcast)
									scope.$broadcast(options.prefixEvent + '.' + status, $target);

							};

							$master.applyEvents = function (status) {

								if (angular.isDefined(options.onShow))
									scope.$on(options.prefixEvent + '.show', function () {
										options.$scope.$eval(options.onShow);
										options.$scope.$apply();
									});
								if (options.onHide)
									scope.$on(options.prefixEvent + '.hide', function () {
										options.$scope.$eval(options.onHide);
										options.$scope.$apply();
									});
							};



							$rootScope.$on('$locationChangeStart', function (event, next, current) {
								$master && $master.$isShown && $master.leave();
							});
							function onBodyClick(evt) {
								if (evt.isDefaultPrevented())
									return false;
								var elm = $master.$currentElement && $master.$currentElement || element;
								if (evt.target === elm[0])
									return false;
								else if (elm.has(angular.element(evt.target)))
									return false;
								else if ((options.multiple || options.overseeingTarget) && (evt.target == $master.$target[0] || $master.$target.has(evt.target)))
									return false;
								return evt.target !== elm[0] && $master.leave();
							}
							function outerHoverTrigger(evt) {
								if ($master.$target[0] == evt.target || $master.$target.has(angular.element(evt.target))) {
									if (evt.type == 'mouseenter')
										return hoverState = 'in';
									else if (evt.type == 'mouseleave') {
										return $master.leave();
									}
								}
							}
							function build() {
								if (options.container === 'self') {
									$container = element;
								} else if (options.container) {
									var modal;
									if (element)
										modal = element.closest('.modal');
									if (modal && modal.length)
										$container = modal;
									else
										$container = angular.isElement(options.container) ? options.container : angular.element(options.container);
								}
								if (!element && (!$container || $container.length < 1))
									$container = angular.element('body');
								$target = $master.$target = shouldCompile ? $compile(linker)(scope, function (clonedElement, scope) {
								}) : linker;
								ensureFixedPlacement();
								scrollCheck();
								$target.addClass('pop-master')
								if (options.typeClass)
									$target.addClass(options.typeClass)
								if (options.displayReflow && options.effect) {
									if ($target)
										$target.remove();
								}
								else {
									$target.hide();
									if ($container) {
										if (/input|button/.test($container[0].tagName.toLowerCase())) {
											$container.after($target)
										} else
											$container.append($target);
									}
									else
										element.after($target)
								}
								$master.applyEvents();

								if (options.animateTarget) {
									$animateTarget = $target.find(options.animateTarget)
									if ($animateTarget.length < 0)
										$animateTarget = $target
									else
										$master.$animateTarget = $animateTarget;
								}
								else {
									$animateTarget = $target
								}

								scope.builded = true;
								if (!$target.data('$scope'))
									$target.data('$scope', scope);
							}
							function complateHide(callback) {
								$master.$hoverShown = false;
								if (options.keyboard && !options.isInput) {
									angular.element(document).off('keyup', $master.$onKeyUp);
									angular.element(document).off('keyup', $master.$onFocusKeyUp);
								}
								if (options.blur && options.trigger === 'focus') {
									element && element.blur();
								}
								element && element.removeClass('active')
								if (options.clearExists && (options.hasClick || options.clearStrict)) {
									angular.element('body').off('click', onBodyClick)
								}
								if (options.holdHoverDelta)
									$target.off('mouseenter mouseleave', outerHoverTrigger);
								callback && callback.call($master);
								$target && $target.css({ top: '', left: '' }).removeClass(lastplacement).removeClass(options.speed);
								if (options.theme)
									$target.removeClass(options.theme).removeClass(options.instanceName + '-' + options.theme);
								$master.$isHidding = false;

							}
							function complateShow(callback) {
								$master.$hoverShown = true;
								if (options.keyboard && !options.isInput) {
									if (options.trigger !== 'focus') {
										angular.element(document).on('keyup', $master.$onKeyUp);
									} else {
										element && angular.element(document).on('keyup', $master.$onFocusKeyUp);
									}
								}
								element && element.addClass('active')

								if (options.clearExists && (options.hasClick || options.clearStrict)) {
									angular.element('body').on('click', onBodyClick)
								}
								if (options.holdHoverDelta)
									$target.on('mouseenter mouseleave', outerHoverTrigger);
								callback && callback.call($master)

							}
							function ensureFixedPlacement() {
								if (options.ensurePlacement && (!options.container || ($container && $container.css("position") === "fixed"))) {
									if ($container && $container.css("position") === "fixed") {
										options.insideFixed = true;
										return false;
									}

									var $checkElements = $target.add($target.parents());
									var isFixed = false;
									var scaleW = angular.element(window).width() / 2;
									var scaleH = angular.element(window).height() / 2;
									angular.forEach($checkElements, function (node) {
										var fx = angular.element(node);
										if (fx.css("position") === "fixed") {
											options.insideFixed = true;
											var val = fx.css("bottom");
											if ((val != 'auto' || val != 'initial') && parseInt(val) < scaleH && options.placement.indexOf("bottom-") > -1) {
												options.placement = options.placement.replace('bottom', 'top');
												options.offsetTop = -1 * options.offsetTop;
												return false;
											}
											val = fx.css("top");
											if ((val != 'auto' || val != 'initial') && parseInt(val) < scaleH && options.placement.indexOf("top-") > -1) {
												options.placement = options.placement.replace('top', 'bottom');
												options.offsetTop = -1 * options.offsetTop;
												return false;
											}
											val = fx.css("left");
											if ((val != 'auto' || val != 'initial') && parseInt(val) < scaleW && options.placement.indexOf("left-") > -1) {
												options.placement = options.placement.replace('left', 'right');
												options.offsetLeft = -1 * options.offsetLeft;
												return false;
											}
											val = fx.css("right");
											if ((val != 'auto' || val != 'initial') && parseInt(val) < scaleW && options.placement.indexOf("right-") > -1) {
												options.placement = options.placement.replace('right', 'left');
												options.offsetLeft = -1 * options.offsetLeft;
												return false;
											}
											return false;
										}
									});
								}


							}
							function scrollCheck() {
								if (options.insideFixed && options.typeClass !== 'modal') {
									scope.$on('staticContentScroll', function () { })
									scope.$on('staticContentScroll', function (obj, top) {
										if ($master.$isShown) {
											$master.$applyPlacement();
										}
									})
								}
							}
							start();
							return $master;
						}
						return MasterFactory;
					}
				];
			})
		angular.forEach(['Modal', 'Dropdown', 'Popover'], function (directive) {
			app.directive('nqToggle' + directive, ['$helpers', '$rootScope', '$sce', '$timeout', function ($helpers, $rootScope, $sce, $timeout) {
				return {
					restrict: 'EA',
					priority: 1000,
					link: function postLink(scope, element, attr, transclusion) {

						var itemId = attr['nqToggle' + directive], target, service, options = {}, togglerId, trigger;

						if (itemId) {
							target = angular.element(itemId);
						}

						if (!itemId || (target && !target.length))
							return;
						togglerId = $helpers.id();
						angular.forEach(props, function (key) {
							if (angular.isDefined(attr[key]))
								attr.$observe(key, function (newValue, oldValue) {
									options[key] = newValue;
								})
						});
						$timeout(function () {
							build();
						}, 300)
						function build() {
							service = target.data('$nq' + directive);
							trigger = angular.isDefined(attr.trigger) ? attr.trigger : 'click';
							if (!angular.isObject(service))
								return;
							options = angular.extend({}, service.$originalOptions, options);
							trigger = angular.isDefined(attr.trigger) ? attr.trigger : options.trigger || 'click';
							if (trigger.indexOf('click'))
								options.hasClick = true;

							element.on(trigger, function () {
								if (service.$isShown) {
									service.hide(function () {
										if (service.togglerId && togglerId !== service.togglerId)
											$timeout(function () {
												show();
											}, 10)
									});
								} else {
									show();
								}
							})

						}
						function show() {
							service.$currentElement = element;
							service.$options = angular.extend({}, options);
							service.togglerId = togglerId;
							extendScope();
							service.show();
						}
						function extendScope() {
							var sScope = service.$scope;
							if (angular.isDefined(attr.qsTitle))
								sScope.title = $sce.trustAsHtml(scope.$eval(attr.qsTitle) || attr.qsTitle);
							if (angular.isDefined(attr.qsContent)) {
								var newContent = scope.$eval(attr.qsContent) || attr.qsContent;
								if (angular.isObject(newContent))
									angular.extend(sScope, newContent);
								else
									sScope.content = $sce.trustAsHtml(newContent);
							}

						}
						scope.$on('$destroy', function () {
							element.off(trigger)
						});
					}
				};
			}]);
		})
	}(window, window.angular);
'use strict';
angular.module('ngQuantum.popover', ['ngQuantum.popMaster'])
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('popover/popover.tpl.html',
			"<div class=\"popover\"><h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3><div class=\"popover-content\" ng-bind-html=\"content\"></div></div>"
		);

	}])
	.provider('$popover', function () {
		var defaults = this.defaults = {
			effect: 'flip-y',
			placement: 'right',
			template: 'popover/popover.tpl.html',
			contentTemplate: false,
			trigger: 'click',
			keyboard: true,
			html: false,
			title: '',
			content: '',
			clearExists: false,
			delay: 0,
			showArrow: true,
			container: 'body',
			directive: 'nqPopover',
			instanceName: 'popover',
			typeClass: 'popover',
			prefixEvent: 'popover',
			displayReflow: false,
			theme: false
		};
		this.$get = [
			'$popMaster', '$sce', '$helpers',
			function ($popMaster, $sce, $helpers) {
				function PopoverFactory(element, config, attr) {

					config = $helpers.parseOptions(attr, config)
					var options = angular.extend({}, defaults, config);

					if (!options.independent && !options.useTemplate) {
						var target;
						if (options.target)
							target = angular.element(options.target);
						else {
							target = angular.element(element.find('.popover')[0]);
							if (target.length < 1)
								target = angular.element(element.next('.popover')[0]);
						}
						if (target.length > 0)
							options.targetElement = target
					}

					var $popover = new $popMaster(element, options, attr);
					var scope = $popover.$scope
					options = $popover.$options = $helpers.observeOptions(attr, $popover.$options);

					if (options.content) {
						$popover.$scope.content = options.content;
					}
					if (attr) {
						angular.forEach(['title', 'content'], function (key) {
							var akey = 'qs' + key.capitaliseFirstLetter();
							attr[akey] && (scope[key] = $sce.trustAsHtml(attr[akey]));
							attr.$$observers && attr.$$observers[akey] && attr.$observe(akey, function (newValue, oldValue) {
								scope[key] = $sce.trustAsHtml(newValue);
							});
						});
						if (attr && angular.isDefined(options.directive)) {
							attr[options.directive] && scope.$watch(attr[options.directive], function (newValue, oldValue) {
								if (angular.isObject(newValue)) {
									angular.extend(scope, newValue);
								} else {
									scope.content = newValue;
								}
							}, true);
						}
					}
					scope.$on('$destroy', function () {
						$popover.destroy();
						$popover = null;
					});
					return $popover;
				}
				return PopoverFactory;
			}
		];
	}).directive('nqPopover', ['$popover',
		function ($popover) {
			return {
				restrict: 'EAC',
				scope: true,
				link: function postLink(scope, element, attr) {
					var options = {
						$scope: scope
					};

					options.uniqueId = attr.qoUniqueId || attr.id || options.$scope.$id;
					if (attr.qoTrigger && attr.qoTrigger.indexOf('hover') > -1) {
						options.holdHoverDelta = true;
						options.delayHide = 100;
						options.delayShow = 10;
					}

					if (angular.isDefined(attr.qsTitle) || angular.isDefined(attr.qsContent) || attr.nqPopover
						|| angular.isDefined(attr.qoTemplate) || angular.isDefined(attr.qoContentTemplate))
						options.useTemplate = true;
					var popover = {};
					if (angular.isDefined(attr.qoIndependent)) {
						options.independent = true;
						options.html = true;
						options.useTemplate = false;
						options.targetElement = element;
						popover = $popover(null, options, attr);

					}
					else
						popover = $popover(element, options, attr);
					scope.$on('$destroy', function () {
						popover = null;
					})
					element.data('$nqPopover', popover)
				}
			};
		}
	]);

'use strict';
if (/chrome/.test(navigator.userAgent.toLowerCase()))
	angular.element('html').addClass('webkitscrollbar');
angular.module('ngQuantum.scrollbar', ['ngQuantum.services.helpers', 'ngQuantum.services.mouse'])
	.provider('$scrollbar', function () {
		var defaults = this.defaults = {
			barSize: 'slimest', // number in pixel or slimmest|slim|normal|thick|thickest
			barOffset: 10,
			maxWidth: false,
			placementOffset: false,
			maxHeight: false,
			useWebkit: false,
			showButtons: false,
			hideRail: false,
			padHorizontal: false,
			allDigest: false,
			step: 30,
			duration: 200,
			theme: false,
			allTags: true, // if set false tags like table, ul, ol would be ignored for scrolling,
			forceWrapper: false, //deprecated
			forceScroll: false, //deprecated
			wrapContainer: false,
			axis: 'y',
			verticalPlacement: 'right', //left|right|both
			horizontalPlacement: 'bottom', //top|bottom|both
			visible: false,
			keyboard: true
		};
		this.$get = ['$mouse', '$window',
			'$compile', '$timeout',
			'$q', '$rootScope', '$helpers', function ($mouse, $window, $compile, $timeout, $q, $rootScope, $helpers) {
				var isTouch = 'createTouch' in $window.document;
				function Factory(element, config, attr) {
					var $bar = {};
					config = $helpers.parseOptions(attr, config);
					var options = angular.extend({}, defaults, config);
					var scope = options.$scope && options.$scope.$new() || $rootScope.$new(), $x = {}, $y = {}, $size = {}, $container, $barListItem;
					$helpers.observeOptions(attr, options);
					$bar.$scope = scope;
					$bar.$options = options;
					scope.scrollTop = 0, scope.scrollLeft = 0;
					element.data('$scrollBar', $bar);
					angular.forEach(['increase', 'decrease'], function (value) {
						scope['$' + value] = function (axis) {
							scope.$$postDigest(function () {
								$bar[value](axis);
							});
						}
					});
					$bar.increase = function (axis) {
						var a = axis == 'y' ? $y : $x;
						var offval = options.step + (axis == 'y' ? scope.scrollTop : scope.scrollLeft),
							tval = a.stepSize + a.thumbStep;
						axis == 'y' ? scrollTop(offval, tval) : scrollLeft(offval, tval);
					}
					$bar.decrease = function (axis) {
						var a = axis == 'y' ? $y : $x;
						var offval = (axis == 'y' ? scope.scrollTop : scope.scrollLeft) - options.step,
							tval = a.stepSize - a.thumbStep;
						axis == 'y' ? scrollTop(offval, tval) : scrollLeft(offval, tval);
					}
					$bar.init = function () {
						optimize();
						buildTemplate();
						if (!$bar.$eventsBuilded)
							buildEvents()
					}
					$bar.destroy = function () {
						element && element.off();
						angular.element(document).off('.scrollbar');
						angular.element(document).off('keydown', $bar.$onKeyDown);
						scope.$destroy();
						$bar = null;
					}
					$bar.$onKeyDown = function (e) {
						if (!/(37|38|39|40)/.test(e.keyCode))
							return;
						if (!e.isDefaultPrevented()) {
							e.preventDefault();
							var code = e.keyCode, evt = e;
							switch (code) {
								case 37:
								case 38:
									evt.deltaY = 1
									break
								case 39:
								case 40:
									evt.deltaY = -1
									break;
							}

							mouseWheel(evt);
						}


					};
					$bar.scrollStepTop = function (val) {
						if (angular.isNumber(val)) {
							var tval = ((val / options.step) * $y.thumbStep) + $y.stepSize;
							scrollTop(scope.scrollTop + val, tval);
						}

					}
					$bar.scrollTo = function (val, axis, diff) {
						if (angular.isNumber(val)) {
							!axis && (axis = 'y');
							var a = axis != 'x' ? $y : $x;
							var tval = (val / options.step) * a.thumbStep;
							axis == 'y' ? scrollTop(val, tval) : scrollLeft(val, tval);
						}
						else {
							var elm = [];
							if (angular.isString(val))
								elm = element.find(val);
							else if (angular.isElement(val))
								elm = val;
							if (elm.length) {
								if (/y|both/.test(options.axis)) {
									setTimeout(function () {
										var lval = elm[0].offsetTop - (diff || 0);
										var tval = (lval / options.step) * $y.thumbStep;
										scrollTop(lval, tval);
									}, 0)

								}
								if (/x|both/.test(options.axis)) {
									setTimeout(function () {
										var lval = elm[0].offsetLeft;
										var tval = (lval / options.step) * $x.thumbStep;
										scrollLeft(lval, tval);
									}, 0)

								}
							}
						}
					}
					$bar.refresh = function (timeout) {
						timeout = timeout || 700;
						setTimeout(function () {
							findSizes();
							watchResult();
						}, timeout)

					};
					function optimize() {
						if (!/y|x|both/.test(options.axis))
							options.axis = 'y';
						!angular.isNumber(options.barOffset) && (options.barOffset = 10)
						!angular.isNumber(options.step) && (options.step = 30)

						if (!/slimmest|slim|normal|thick|thickest/.test(options.barSize)) {
							$size.barSize = parseInt(options.barSize) || 6;
						}
						else {
							scope.sizeClass = 'bar-' + options.barSize
							switch (options.barSize) {
								case 'slimmest':
									$size.barSize = 4;
									break;
								case 'slim':
									$size.barSize = 8;
									break;
								case 'normal':
									$size.barSize = 12;
									break;
								case 'thick':
									$size.barSize = 16;
									break;
								case 'thickest':
									$size.barSize = 20;
									break;
								default:
									$size.barSize = 6;
									break;
							}
						}
						if ($size.barSize <= 12)
							$size.buttonSize = 12;
						else
							$size.buttonSize = $size.barSize;
						if (options.axis == 'both' && options.barOffset < $size.buttonSize)
							options.barOffset = $size.buttonSize + 5;
						if (options.useWebkit && angular.element('html').hasClass('webkitscrollbar'))
							scope.useWebkit = true;
					}

					function buildTemplate() {
						if ($bar && $bar.$templateReady)
							return;
						$bar.$templateReady = true;
						checkAdaptable();
						$container.addClass('scrollable')
						var pos = $container.css('position');
						scope.elPosition = pos;
						if (scope.useWebkit) {
							if (/y|both/.test(options.axis))
								$container.css('overflow-y', 'auto');
							if (/x|both/.test(options.axis))
								$container.css('overflow-x', 'auto');
							return;
						}
						if (options.axis == 'y')
							$container.css('overflow-y', 'hidden');
						else if (options.axis == 'x')
							$container.css('overflow-x', 'hidden');
						else
							$container.css('overflow', 'hidden');
						if (!/relative|absolute|fixed/.test(pos)) {
							$container.css('position', 'relative')
						}
						var barBody = $barListItem ? $barListItem : $container;
						if (/y|both/.test(options.axis)) {
							$y.bar = angular.element('<div class="scrollbar vertical-bar"></div>').appendTo(barBody).addClass('bar-' + options.verticalPlacement);
							$y.track = angular.element('<div class="scrollbar-track"></div>').appendTo($y.bar);
							$y.trackInner = angular.element('<div class="track-inner"></div>').appendTo($y.track).css('width', $size.barSize);
							$y.thumb = angular.element('<div class="scrollbar-thumb"></div>').appendTo($y.trackInner);
							if (options.showButtons) {
								$y.increment = angular.element('<a class="bar-increment" ng-click="$increase(\'y\')"><span></span></a>').appendTo($y.bar).css('height', $size.buttonSize)
								$y.decrement = angular.element('<a class="bar-decrement" ng-click="$decrease(\'y\')"><span></span></a>').prependTo($y.bar).css('height', $size.buttonSize)
								$compile($y.bar)(scope);
							}
							if (angular.isNumber(options.placementOffset)) {
								$y.bar.css(options.verticalPlacement, options.placementOffset)
							}
							$y.placementOffset = parseInt($y.bar.css(options.verticalPlacement)) || 0;
							if (!isTouch) {
								$y.trackInner.on('click', function (evt) {
									if (evt.target == this) {
										var tp = evt.offsetY
										if (tp > $y.stepSize)
											tp = tp - $y.thumb.height();
										var step = parseInt(tp / $y.thumbStep);
										var top = options.step * step, ttop = step * $y.thumbStep;
										scrollTop(top, ttop);
									}
								})
								$y.thumb.on('mousedown', function (e) {
									var last = $y.stepSize;
									if (e.which != 1)
										return true;
									angular.element(document).on('mousemove.scrollbar', function (evt) {
										var i = (evt.pageY - e.pageY) + last;
										var step = i / $y.thumbStep;
										var top = (options.step * step), ttop = (step * $y.thumbStep);
										scrollTop(top, ttop);
									})
								})
							}
						}
						if (/x|both/.test(options.axis)) {
							var pad = options.showButtons ? $size.buttonSize : $size.barSize
							$x.bar = angular.element('<div class="scrollbar horizontal-bar"></div>').appendTo(barBody).addClass('bar-' + options.horizontalPlacement);
							$x.track = angular.element('<div class="scrollbar-track"></div>').appendTo($x.bar);
							$x.trackInner = angular.element('<div class="track-inner"></div>').appendTo($x.track).css('height', $size.barSize);
							$x.thumb = angular.element('<div class="scrollbar-thumb"></div>').appendTo($x.trackInner);
							if (options.showButtons) {
								$x.increment = angular.element('<a class="bar-increment" ng-click="$increase(\'x\')"><span></span></a>').appendTo($x.bar)
								$x.decrement = angular.element('<a class="bar-decrement" ng-click="$decrease(\'x\')"><span></span></a>').prependTo($x.bar)
								$compile($x.bar)(scope)

							}
							if (options.padHorizontal)
								if (options.horizontalPlacement == 'top') {
									var pt = parseInt($container.css('padding-top')) || 0;
									$container.css('padding-top', pad + pt + 10)
								}
								else {
									var pt = parseInt($container.css('padding-bottom')) || 0;
									$container.css('padding-bottom', pad + pt + 10)
								}
							if (angular.isNumber(options.placementOffset)) {
								$x.bar.css(options.horizontalPlacement, options.placementOffset)
							}
							$x.placementOffset = parseInt($x.bar.css(options.horizontalPlacement)) || 0;
							if (!isTouch) {
								$x.trackInner.on('click', function (evt) {
									if (evt.target == this) {
										var tp = evt.offsetX
										if (tp > $x.stepSize)
											tp = tp - $x.thumb.width();
										var step = parseInt(tp / $x.thumbStep);
										var left = options.step * step, tleft = step * $x.thumbStep;
										scrollLeft(left, tleft);
									}
								})
								$x.thumb.on('mousedown', function (e) {
									angular.element(document).off('.scrollbar')
									var last = $x.stepSize;
									if (e.which != 1)
										return true;
									angular.element(document).on('mousemove.scrollbar', function (evt) {
										var i = (evt.pageX - e.pageX) + last;
										var step = i / $x.thumbStep;
										var left = (options.step * step), tleft = (step * $x.thumbStep);
										scrollLeft(left, tleft);
									})
								})
							}

						}
						!isTouch && angular.element('body').on('mouseup', function (evt) {
							angular.element(document).off('.scrollbar')
						});


						$container.addClass('show-bar-button')
					}
					function buildEvents() {
						if (!scope.useWebkit || isTouch) {
							if (options.allDigest)
								scope.$watch(function (newVal, oldVal) {
									setTimeout(function () {
										watchResult();
									}, 0)
								})
							else {
								var el = $container || element;
								if (/y|both/.test(options.axis))
									scope.$watch(function () { return el[0].scrollHeight }, function (newVal, oldVal) {
										setTimeout(function () {
											watchResult();
										}, 0)

									})
								if (/x|both/.test(options.axis))
									scope.$watch(function () { return el[0].scrollWidth }, function (newVal, oldVal) {
										setTimeout(function () {
											watchResult();
										}, 0)
									})
							}

							if (!isTouch) {
								$mouse.onWheel(element, mouseWheel);
								element.on('mouseenter', function (e) {
									if (/y|both/.test(options.axis) && !scope._scrollHeight)
										watchResult();
									if (/x|both/.test(options.axis) && !scope._scrollWidth)
										watchResult();
									if (options.keyboard) {
										angular.element(document).off('.scrollbarkeyboard', $bar.$onKeyDown);
										angular.element(document).on('keydown.scrollbarkeyboard', $bar.$onKeyDown);
									}

								})
								options.keyboard && element.on('mouseleave', function (e) {
									angular.element(document).off('keydown', $bar.$onKeyDown);
								})
							}
							else {
								element.on('touchstart', function (event) {
									var lastY = $y.stepSize || 0, lastX = $x.stepSize || 0;
									var sTouch = event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];
									$y.bar && $y.bar.css('visibility', 'visible');
									$x.bar && $x.bar.css('visibility', 'visible');
									angular.element(document).on('touchmove.scrollbar', function (evt) {
										var touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
										var newY = (sTouch.pageY - touch.pageY) + lastY;
										var newX = (sTouch.pageX - touch.pageX) + lastX;
										var retuned = false;
										if (/y|both/.test(options.axis)) {
											if (!$y.maxOffset && options.axis == 'y')
												retuned = true;
											if (scope.scrollTop == $y.maxOffset && sTouch.pageY > touch.pageY)
												retuned = true;
											if (scope.scrollTop == 0 && sTouch.pageY < touch.pageY)
												retuned = true;
										}
										if (/x|both/.test(options.axis)) {
											if (!$x.maxOffset && options.axis == 'x')
												retuned = true;
											if (scope.scrollLeft == $x.maxOffset && sTouch.pageX > touch.pageX)
												retuned = true;
											if (scope.scrollLeft == 0 && sTouch.pageX > touch.pageX)
												retuned = true;
										}
										if (options.axis == 'both' && !$y.maxOffset && !$x.maxOffset)
											retuned = true;
										if (retuned)
											return true;
										event.preventDefault();
										evt.preventDefault();
										if (/y|both/.test(options.axis)) {
											var step = newY / $y.thumbStep;
											var top = (options.step * step), ttop = (step * $y.thumbStep);
											scrollTop(top, ttop);
										}
										if (/x|both/.test(options.axis)) {
											var step = newX / $x.thumbStep;
											var left = (options.step * step), tleft = (step * $x.thumbStep);
											scrollLeft(left, tleft);
										}

									})
								})
								angular.element(document).on('touchend.scrollbar touchcancel.scrollbar', function (evt) {
									$y.bar && $y.bar.css('visibility', 'hidden');
									$x.bar && $x.bar.css('visibility', 'hidden');
									angular.element(document).off('touchmove')
								})
							}


						}
						$bar.$eventsBuilded = true;
					}

					function watchResult() {
						if ($container && $container.height() < 0 || !$container && element && element.height() < 1)
							return;
						$y.bar && $y.bar.hide();
						$x.bar && $x.bar.hide();
						var tag = element[0].tagName, width = 0, height = 0;
						var pad = options.showButtons ? $size.buttonSize : $size.barSize;
						if (/td|th|table/.test(tag.toLowerCase())) {
							if ($container) {
								height = $container[0].scrollHeight - pad;
								width = $container[0].scrollWidth;
							}
							else {
								height = element[0].clientHeight - pad;
								width = element[0].clientWidth;
							}
						}
						else {
							height = element[0].scrollHeight - pad;
							width = element[0].scrollWidth;
						}
						if (/y|both/.test(options.axis)) {
							if (height > 0 && scope.maxHeight < height && $container && $container.outerHeight() >= scope.maxHeight && ($container[0].scrollHeight > $container[0].clientHeight)) {
								scope._scrollHeight = height, applyY(height);
								$y.bar && $y.bar.css('visibilty', '').show();
								$y.bar.visible = true;
							} else {
								$container.scrollTop(0)
								$y.bar && $y.bar.css('visibilty', 'hidden');
								$y.bar.visible = false;
							}
							if (scope.scrollTop > 0 && $container.height() < height) {
								$container.scrollTop(scope.scrollTop);
							}
						}
						if (/x|both/.test(options.axis)) {
							if (width > 0 && scope.maxWidth < width && $container.outerWidth() >= scope.maxWidth && $container && ($container[0].scrollWidth > $container[0].clientWidth)) {
								scope._scrollWidth = width, applyX(width);
								$x.bar && $x.bar.css('visibilty', '').show();
								$x.bar.visible = true;
							} else {
								$container.scrollLeft(0)
								$x.bar && $x.bar.css('visibilty', 'hidden')
								$x.bar.visible = false;
							};


							if (scope.scrollLeft > 0 && $container.width() < width) {
								$container.scrollLeft(scope.scrollLeft);
							}
						}
					}
					function mouseWheel(event) {
						if (options.axis == 'y') {
							if (!$y.bar.visible)
								return true;
							if (!scope._scrollHeight)
								watchResult();
							if (!$y.maxOffset)
								return true;
							if (scope.scrollTop >= $y.maxOffset && event.deltaY < 0)
								return true;

							if (scope.scrollTop == 0 && event.deltaY > 0)
								return true;
							event.preventDefault();
							wheelTop(event)
						}
						else if (options.axis == 'x') {
							if (!$x.bar.visible)
								return true;
							if (!$x.maxOffset)
								return true;
							if (scope.scrollLeft >= $x.maxOffset && event.deltaY < 0)
								return true;
							if (scope.scrollLeft == 0 && event.deltaY > 0)
								return true;
							event.preventDefault();
							wheelLeft(event)
						}
						else if (options.axis == 'both') {
							if ($y.maxOffset && scope.scrollTop < $y.maxOffset && event.deltaY < 0) {
								event.preventDefault();
								wheelTop(event)
							}
							else if ($x.maxOffset && scope.scrollLeft < $x.maxOffset && event.deltaY < 0) {
								event.preventDefault();
								wheelLeft(event)
							}
							else if (scope.scrollLeft > 0 && event.deltaY > 0) {
								event.preventDefault();
								wheelLeft(event)
							}
							else if (scope.scrollTop > 0 && event.deltaY > 0) {
								event.preventDefault();
								wheelTop(event)
							}
							else
								return true;
						}
					}
					function wheelTop(event) {
						var top = scope.scrollTop;
						top = event.deltaY > 0 ? top - options.step : top + options.step;
						var mtop = event.deltaY > 0 ? $y.stepSize - $y.thumbStep : $y.stepSize + $y.thumbStep;

						scrollTop(top, mtop)
					}
					function scrollTop(btop, ttop) {
						btop = validateOffset(btop, $y.maxOffset)
						ttop = validateOffset(ttop, $y.maxThumbOffset);
						$y.stepSize = ttop;
						$container.scrollTop(btop);
						$y.thumb && $y.thumb.css('top', ttop + 'px');
						$y.bar && $y.bar.css('top', btop + options.barOffset + 'px')
						if ($x.bar) {
							$x.bar.css(options.horizontalPlacement, -(btop - $x.placementOffset))
						}
						scope.scrollTop = btop;
					}
					function wheelLeft(event) {
						var left = scope.scrollLeft;
						left = event.deltaY > 0 ? left - options.step : left + options.step;
						var mleft = event.deltaY > 0 ? $x.stepSize - $x.thumbStep : $x.stepSize + $x.thumbStep;

						scrollLeft(left, mleft);
					}
					function scrollLeft(left, mleft) {
						left = validateOffset(left, $x.maxOffset)
						mleft = validateOffset(mleft, $x.maxThumbOffset)
						$x.stepSize = mleft;
						$container.scrollLeft(left);
						$x.thumb && $x.thumb.css('left', mleft + 'px');
						$x.bar && $x.bar.css('left', left + options.barOffset + 'px')
						if ($y.bar) {
							$y.bar.css(options.verticalPlacement, -(left - $y.placementOffset))
						}
						scope.scrollLeft = left;

					}
					function validateOffset(val, max) {
						var result = val;
						if (val > max)
							result = max + 0.1;
						if (val < 0)
							result = 0
						return result;
					}
					function barSizes(axis, newsize, elsize) {
						var $a = axis, oldStepRange = ($a.stepSize && $a.thumbStep) && ($a.stepSize / $a.thumbStep);
						var s = elsize,
							bs = s - (2 * options.barOffset),
							ts = s * s / newsize;
						$a.barSize = bs;
						$a.trackSize = bs;
						if (options.showButtons) {
							$a.trackSize = bs - ($size.buttonSize * 2) - 6;
						}
						$a.thumbSize = ts;
						$a.maxOffset = newsize - s;
						var mts = $a.trackSize - ts;
						$a.maxThumbOffset = mts;
						$a.thumbStep = (($a.trackSize - ts) / ($a.maxOffset / options.step))
						$a.stepSize = oldStepRange ? (oldStepRange * $a.thumbStep) : 0;
						$a.stepSize > $a.maxThumbOffset && ($a.stepSize = $a.maxThumbOffset);
						return $a;
					}
					function checkAdaptable() {
						var tag = element[0].tagName;
						findSizes();
						if (/ul|ol/.test(tag.toLowerCase()) && !scope.useWebkit) {
							$barListItem = angular.element('<li class="scrollbar-list-item"></li>').appendTo(element);
							$container = element;
						}
						else if (tag.toLowerCase() == 'table') {
							$container = angular.element('<div class="scrollbar-container"></div>').insertBefore(element).append(element);
							applySizes();
						}
						else if (/td|th/.test(tag.toLowerCase())) {
							$container = angular.element('<div class="scrollbar-container"></div>').appendTo(element);
							applySizes();
						}
						else {
							$container = element;
							if (options.maxWidth || options.maxHeight)
								applySizes();
						}
						scope.sizeClass && $container.addClass(scope.sizeClass);
						options.theme && $container.addClass('bar-' + options.theme);
						options.visible && $container.addClass('bar-visible');
						options.hideRail && $container.addClass('hide-rail');
						!scope.useWebkit && $container.addClass('no-webkit');
						!options.showButtons && $container.addClass('hide-bar-button');
					}
					function findSizes() {
						var exchild = false;
						$size.width = options.maxWidth ? options.maxWidth : element.css('max-width') || element.css('width');
						$size.height = options.maxHeight ? options.maxHeight : element.css('max-height') || element.css('height');
						scope.maxWidth = angular.isNumber($size.width) ? $size.width : angular.isString($size.width)
							? $size.width.indexOf('%') !== -1 ? (element.parent().innerWidth() * ((parseFloat($size.width) / 100) || 0)) : parseFloat($size.width) || 0 : 0;
						scope.maxHeight = angular.isNumber($size.height) ? $size.height : angular.isString($size.height)
							? $size.height.indexOf('%') !== -1 ?
								function () {
									exchild = true;
									return element.parent().innerHeight() * ((parseFloat($size.height) / 100) || 0)
								}() : parseFloat($size.height) || 0 : 0;
					}
					function applySizes(elm) {
						var cont = elm ? elm : $container;
						if (/y|both/.test(options.axis)) {
							cont.css('max-height', $size.height)
						}
						if (/x|both/.test(options.axis))
							cont.css('max-width', $size.width)
					}
					function applyY(newval) {
						newval = newval || $container[0].scrollHeight;

						var maxtop = $container[0].scrollHeight - $container.outerHeight();
						if (maxtop < scope.scrollTop)
							scope.scrollTop = maxtop;
						if (newval && /y|both/.test(options.axis)) {
							var h = $container.outerHeight(true);
							$y = barSizes($y, newval, h);
							if (!$bar || !$bar.$templateReady)
								buildTemplate();
							$y.bar.css({
								top: (scope.scrollTop || 0) + options.barOffset + 'px',
								bottom: options.barOffset + 'px',
								height: $y.barSize + 'px'
							})
							$y.thumb.css({
								height: $y.thumbSize + 'px',
								top: $y.stepSize + 'px'
							})
							$y.track.css({
								height: $y.trackSize + 6 + 'px'
							})
						}
					}
					function applyX(newval) {
						newval = newval || $container[0].scrollWidth;
						var maxleft = $container[0].scrollWidth - $container.outerWidth();
						if (maxleft < scope.scrollLeft)
							scope.scrollTop = maxleft;
						if (newval && /x|both/.test(options.axis)) {
							var w = $container.outerWidth(true)
							$x = barSizes($x, newval, w);

							if (!$bar.$templateReady)
								buildTemplate();
							$x.bar.css({
								left: (scope.scrollLeft || 0) + options.barOffset + 'px',
								right: options.barOffset + 'px',
								width: $x.barSize + 'px'
							})
							$x.thumb.css({
								width: $x.thumbSize + 'px',
								left: $x.stepSize + 'px'
							})
							$x.track.css({
								width: $x.trackSize + 6 + 'px'
							})
						}
					}
					options.$scope && options.$scope.$on('$destroy', function () {
						$bar.destroy();

					})
					var windowResize = function () {
						$timeout(function () {
							$bar.refresh(200)
						}, 100)
					};

					window.addResizeEvent(windowResize)
					angular.element(document).ready(function () {
						setTimeout(function () {
							windowResize();
						}, 200)

					})
					$bar.init();
					return $bar;
				};
				return Factory;
			}];
	})
	.directive('nqScroll',
	['$scrollbar', '$timeout', function ($scrollbar, $timeout) {
		return {
			restrict: 'AC',
			isolate: false,
			link: function postLink(scope, element, attr) {
				setTimeout(function () {
					var bar = $scrollbar(element, { $scope: scope }, attr)
					if (attr.barModel)
						scope[attr.barModel] = bar;
				}, 10)
			}
		};
	}])

	+ function (window, angular, undefined) {
		'use strict';
		var selectApp = angular.module('ngQuantum.select', [
			'ngQuantum.popMaster',
			'ngQuantum.scrollbar'
		])
			.run(['$templateCache', function ($templateCache) {
				'use strict';
				$templateCache.put('select/select.tpl.html',
					'<div tabindex="-1" class="listbox-panel ng-cloak" role="listbox"><div class="scrollable" role=\"listbox\"><ul tabindex=\"-1\" class=\"listbox\"><li role=\"presentation\" tabindex=\"-1\" ng-repeat=\"match in $matches track by $index\"><span class=\"select-option option-label\"  role=\"option\" tabindex=\"-1\" ng-click=\"$select(match)\" ng-bind=\"match.label\"></span> </li></ul></div></div>'
				);
				$templateCache.put('select/selectgroup.tpl.html',
					'<div tabindex="-1" role="listbox" class="listbox-panel ng-cloak"><div tabindex="-1" class="scrollable" role="listbox"> <ul tabindex="-1" class="listbox"> <li tabindex="-1" role="presentation" ng-repeat="match in $groupMatches">  <span class="select-option" ng-if="!match.items" role="option" tabindex="-1" ng-disabled="match.disabled" ng-click="$select(match)"> <span class="option-label" ng-bind="match.label"></span> </span> <div tabindex="-1" class="option-group" ng-if="match.items" ng-disabled="match.disabled"> <span class="group-label" ng-bind="match.label"></span> <ul tabindex="-1">  <li tabindex="-1" role="presentation" data-ng-repeat="item in match.items track by $index"> <span class="select-option" role="option" tabindex="-1" ng-disabled="item.disabled" ng-click="$select(item)"><span class="option-label" ng-bind="item.label"></span></span></li></ul></div></li></ul></div></div>'
				);
			}])
			.provider('$select', function () {
				var defaults = this.defaults = {
					effect: 'sing',
					typeClass: 'select',
					prefixClass: 'select',
					buttonClass: 'btn-default',
					navClass: 'nav-mixed',
					prefixEvent: 'select',
					placement: 'bottom-left',
					template: 'select/select.tpl.html',
					groupTemplate: 'select/selectgroup.tpl.html',
					trigger: 'click',
					fireEmit: false,
					lazyAjax: true,
					container: 'body',
					displayReflow: false,
					disableClear: false,
					keyboard: true,
					multiple: false,
					filterable: true,
					highlight: true,
					showTick: true,
					urlPrefix: false,
					isQuerystring: false,
					cacheResult: true,
					caseSensitive: true,
					seperator: ', ',
					html: true,
					clearIcon: '<span class="clear-icon fu-cross"></span>',
					spinner: '<span class="spin-icon fu-spinner-fan spin"></span>',
					noMatch: 'No result found...',
					placeholder: 'Please select...',
					filterText: 'search...',
					charText: 'Please enter {{$remainingChar}} or more characters',
					searchingText: 'Searching...',
					maxLength: 3,
					maxTextLength: 30,
					minTextLength: 3,
					minChar: 3,
					forceHide: false,
					selectedRemovable: true
				};
				this.$get = [
					'$filter',
					'$window',
					'$http',
					'$compile',
					'$rootScope',
					'$popMaster',
					'$parseOptions',
					'$timeout',
					'$q',
					'$scrollbar',
					'$lazyRequest',
					'$helpers',
					function ($filter, $window, $http, $compile, $rootScope, $popMaster, $parseOptions, $timeout, $q, $scrollbar, $lazyRequest, $helpers) {
						var bodyEl = angular.element($window.document.body);
						var isTouch = 'createTouch' in $window.document;
						function SelectFactory(element, controller, config, attr, targetEl) {
							config = $helpers.parseOptions(attr, config);
							!config.template && config.grouped && (config.template = defaults.groupTemplate)
							var $select = {}, inputItem, scrollbar;
							var searchInput = angular.element(['<input ng-hide="$hideFilter" ng-model="filterModel.label" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="{{$placeholder}}" class="select-input form-control" role="combobox" aria-expanded="true"',
								, ' aria-autocomplete="list" style="max-width:100%;" />'].join(""))

							var options = angular.extend({}, defaults, config);
							var isTagsInput = controller.isTagsInput = (options.directive == 'nqTagsInput');
							var clearIcon = options.clearIcon;
							var noMatch, charLabel, searchLabel;
							if (options.filterable) {
								if (angular.isString(options.noMatch) && options.noMatch.length > 2 && options.noMatch.substr(0, 1) == '#')
									noMatch = angular.element(document).find(options.noMatch)
								else
									noMatch = angular.element('<span>' + options.noMatch + '</span>');
								!noMatch.length && (noMatch = null)
								if (noMatch)
									noMatch.addClass('no-match').attr('ng-show', '$noResultFound')
							}
							if (options.inline) {
								options.show = true;
								options.trigger = false;
								options.showArrow = false;
								options.container = false;
								element.addClass('listbox-inline');
								options.effect = false;
								options.autoHide = false;
							}
							$select = new $popMaster(element, options);
							var scope = $select.$scope;
							options = $select.$options = $helpers.observeOptions(attr, $select.$options);
							$select.optionData = [];
							scope.$matches = [];
							scope.urlParams = [];
							$select.searchInput = searchInput;
							scope.$selectedIndex = options.multiple ? [] : -1;
							scope.$isMultiple = options.multiple;
							scope.$remainingChar = options.minChar;
							scope.$placeholder = options.displayType == 'input' ? options.placeholder : options.filterText;
							scope.$select = function (index, evt) {
								scope.$$postDigest(function () {
									$select.select(index);
								});
							};
							var init = $select.init, $target;
							$select.init = function () {
								init();
								options.displayType !== 'input' && element.addClass(options.buttonClass)
								$target = $select.$target;
								if (options.filterable && $target) {
									$compile(searchInput)(scope)

									if (options.displayType == 'input') {
										options.navClass && element.addClass(options.navClass);
										options.inputSize && element.addClass(options.inputSize)
										inputItem = angular.element('<li></li>').append(searchInput.removeClass('form-control').removeClass('input-xs'))
										element.append(inputItem)
										!options.multiple && element.addClass('single-option')
									}
									else {
										options.buttonClass && element.addClass(options.buttonClass)
										$target.prepend(searchInput);
										searchInput.on('click', function (e) {
											e.preventDefault();
											searchInput.focus();
										})
									}
								}
								if (noMatch) {
									$compile(noMatch)(scope)
									$target.append(noMatch)
								}

								options.showTick && $target.addClass('show-tick')

								if (options.url && !options.remoteSearch) {
									if (options.lazyAjax) {
										$lazyRequest(function () {
											return $select.loadRemote();
										}, 0)
									}
									else
										$select.loadRemote();
								}

								if (options.remoteSearch) {
									charLabel = angular.element('<span ng-show="$remainingChar > 0"></span>').append(options.charText)
									searchLabel = angular.element('<span class="search-label" ng-show="$dataLoading"></span>').append(options.searchingText)
									options.spinner && searchLabel.append(options.spinner)
									$compile(charLabel)(scope)
									$compile(searchLabel)(scope)
									$target.append(charLabel);
									$target.append(searchLabel);
								}
								$select.complated = true;
								if (!$select.renderComplated)
									$select.render();
								!(options.displayType == 'input') && element.addClass('select-toggle')

								searchInput && searchInput.attr('maxlength', options.maxTextLength);
								if ($target) {
									var barelement = $target.find('.scrollable');
									var barOptions = {
										keyword: false,
										barSize: 'slimmest',
										placementOffset: -2,
										$scope: scope
									}
									scrollbar = $scrollbar(barelement, barOptions);
								}
							};
							$select.update = function (matches) {
								var selected = $filter('filter')($select.optionData, { selected: true })
								$select.optionData = matches;
								angular.forEach(selected, function (item) {
									$select.addOption(item)
								})
								$select.updateMatches()
							};
							$select.addOption = function (item) {
								var exists = $filter('filter')($select.optionData, function (val, i) {
									if (!options.caseSensitive && (angular.isString(val.label)))
										return val.label.toLowerCase() == (angular.isString(item.label) ? item.label.toLowerCase() : item.label)
									return val.value == item.value;
								});
								if (!exists.length) {
									$select.optionData.push(item);
									scope.$matches = $select.optionData;
									return $select.optionData[$select.optionData.length - 1];
								}
								return exists[0]


							};
							$select.changeOption = function (key, value) {
								options[key] = value;
							};
							$select.updateMatches = function (matches, isfilter) {
								scope.$matches = matches || $select.optionData;
								if (options.grouped)
									scope.$groupMatches = $filter('groupOption')(scope.$matches);
								scope.$noResultFound = !scope.$matches.length;
								if (isTagsInput, isfilter) {
									scope.$noResultFound = !(($filter('filter')(scope.$matches, function (val) { return val.filtered != true })).length)

									scope.$noResultFound ? $select.hide() : $select.show();
								}
							};
							$select.select = function (item) {
								if (options.multiple) {
									if (!item.selected && options.maxLength && (controller.$modelValue && controller.$modelValue.length == options.maxLength))
										return
									else {
										scope.$apply(function () {
											item.selected = isTagsInput ? true : item.selected ? false : true;
											item.filtered = isTagsInput && item.selected;
										})
										var selected = []
										$filter('filter')($select.optionData, function (opt) {
											opt.selected && selected.push(opt.value);
										})
										$timeout(function () {
											controller.$setViewValue(selected);
										}, 0)
									}
								} else {
									if (!scope.fistChanged) {
										$filter('filter')($select.optionData, function (itm, key) {
											if (itm.selected) {
												;
												scope.$lastSelected = itm
												scope.fistChanged = true;
											}
										})
									}

									scope.$apply(function () {
										item.selected = true;
									})
									scope.$lastSelected && !(scope.$lastSelected === item) && (scope.$lastSelected.selected = false);
									scope.$lastSelected = item;
									$timeout(function () {
										controller.$setViewValue(item.value);
									}, 0)
								}
								$timeout(function () {
									$select.render();
								}, 0)

								if (!options.multiple) {
									if (options.trigger === 'focus')
										element[0].blur();
									else if ($select.$isShown || $select.$isHidding)
										$select.hide();
								}
								if (isTagsInput)
									$select.hide();
								scope.$emit('$select.select', item);
								searchInput.val('')
							};
							$select.$getIndex = function (value) {
								var l = $select.optionData.length, i = l;
								if (!l)
									return;
								for (i = l; i--;) {
									if ($select.optionData[i].value === value)
										break;
								}
								if (i < 0)
									return;
								return i;
							};
							$select.$onMouseDown = function (evt) {
								evt.preventDefault();
								evt.stopPropagation();
								if (isTouch) {
									var targetEl = angular.element(evt.target);
									targetEl.triggerHandler('click');
								}
							};
							$select.$onKeyDown = function (e) {
								if (!/(38|40|13)/.test(e.keyCode))
									return true;
								e.preventDefault();
								e.stopPropagation();

								var $items = $target.find('.select-option:visible');

								if (!$items || !$items.length) return;
								$target.focus();
								var index = scope.$lastIndex > -1 ? scope.$lastIndex : -1;
								if (index == -1) {
									var elSelected = angular.element($target.find('.selected')[0]),
										sIndex = elSelected.length && elSelected.scope().$index;
									index = angular.isDefined(sIndex) ? sIndex : elSelected.hasClass('select-option') ? elSelected.parent().index() : elSelected.closest('.select-option').index();
								}
								index >= $items.length && (index = 0)
								if (e.keyCode == 38 && index > 0) index--                  // up
								if (e.keyCode == 40 && index < $items.length - 1) index++  // down
								if (!~index) index = 0

								if (e.keyCode === 13) {
									var match = $filter('filter')(scope.$matches, function (itm) { return itm.filtered != true })[index]
									if (match)
										return $select.select(match);
								}
								$items.eq(index).focus();
								scope.$lastIndex = index;

							};

							var _show = $select.show;
							$select.show = function () {
								var promise = _show();
								if (options.multiple) {
									$select.$target.addClass('select-multiple');
								}
								if (options.keyboard && $select.$target) {
									angular.element(document).off('keydown', $select.$onKeyDown);
									angular.element(document).on('keydown', $select.$onKeyDown);
								}

								$select.$target.css('min-width', element.outerWidth(true));
								promise && promise.then(function () {
									if (options.filterable) {
										if (options.directive != 'nqTagsInput')
											scope.filterModel = { label: '' };
										setTimeout(function () {
											searchInput.focus();
										}, 0);
									}
									if (scrollbar) {
										scrollbar.scrollTo('.selected', null, 60);
									}
									$select.$target.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
								})
							};
							var _hide = $select.hide;
							$select.hide = function () {
								$select.$target.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
								if (options.keyboard && $select.$target)
									angular.element(document).off('keydown', $select.$onKeyDown);

								if (options.directive != 'nqTagsInput')
									searchInput.val('');
								scope.$lastIndex = -1;
								if (options.inline)
									return $q.when('');


								var promise = _hide() || $q.when('');
								promise.then(function () {
									if (options.directive != 'nqTagsInput') {
										scope.filterModel = { label: '' };
										setTimeout(function () {
											searchInput.blur();
										}, 0);
									}
								})
							};

							$select.render = function () {
								if (controller.$modelValue && options.modelIsLabel) {
									if ($select.complated) {
										if (angular.isArray(controller.$modelValue)) {
											angular.forEach(controller.$modelValue, function (val) {
												var item = { label: val, value: val, selected: true, filtered: isTagsInput }
												item = $select.addOption(item)
											})
										}
										else if (options.modelIsLabel) {
											$select.addOption({ label: controller.$modelValue, value: controller.$modelValue, selected: true, filtered: isTagsInput })

										}
										renderController();
									}
								}
								else if (controller.$modelValue && options.remoteSearch && !$select.optionData.length) {
									if (options.lazyAjax) {
										$lazyRequest(function () {
											return $select.loadRemote(null, controller.$modelValue);
										}, 0)
									}
									else
										$select.loadRemote(null, controller.$modelValue);
								}
								else if ($select.complated)
									renderController();
								validateModel();

							};
							$select.loadRemote = function (term, data) {
								scope.$dataLoading = true;
								var post = (data && data.length) ? true : false;
								var url = buildUrl(term, post)
								var ajax = {
									url: url
								}
								ajax.method = post ? 'POST' : 'GET';
								ajax.cache = options.cacheResult;
								post && (ajax.data = { ModelValue: data });
								return $http(ajax)
									.success(function (res) {
										if (options.resultKey)
											scope[options.resultKey] = res.data ? res.data : res;
										else
											scope.selectOptions = res.data ? res.data : res;
										scope.$dataLoading = false;
										scope.$noResultFound = res.data ? !res.data.length : !res.length
										!$select.fistLoad && setTimeout(function () {
											renderController();
										}, 0)
										$select.fistLoad = true;
										term && (scope.lastTerm = term);
									})
									.error(function (res) {
										scope.$dataLoading = false;
										scope.$noResultFound = true;
									})
							}
							if (options.filterable)
								scope.$watch('filterModel.label', function (newValue, oldValue) {
									if (options.remoteSearch)
										remoteFiler(newValue, oldValue)
									else
										localFiler(newValue, oldValue);

									if (searchInput && newValue) {
										searchInput.css('min-width', newValue.length * 0.7 + 'em')
									}
									var scrollVal = newValue ? 0 : '.selected';
									if (scrollbar && newValue) {
										scrollbar.scrollTo(scrollVal, 'y', 10);
									}

								});
							if (attr) {
								angular.forEach(['urlParams'], function (key) {
									attr[key] && attr.$observe(key, function (newValue, oldValue) {
										scope[key] = newValue;
									});
								});
							}
							if (angular.isDefined(attr.ngOptions)) {
								var parsedOptions = $parseOptions(attr.ngOptions);
								var watchedOptions = parsedOptions.$match[7].replace(/\|.+/, '').trim();
								scope.$watch(watchedOptions, function (newValue, oldValue) {
									parsedOptions.valuesFn(scope, controller).then(function (values) {
										if (values && angular.isArray(values)) {
											$select.update(values);
											$select.render();
										}
									});
								});
							}
							else if (targetEl.is('select')) {
								$q.when(targetEl).then(function (el) {
									var parsedOptions = $parseOptions(null, el);
									if (parsedOptions.$values && angular.isArray(parsedOptions.$values)) {
										$select.update(parsedOptions.$values);
										controller.$render();
									}
								});
							}
							else {
								controller.$render();
							}
							if (angular.isDefined(attr.ngChange)) {
								scope.$parent.$watch(function () { return controller.$modelValue }, function (newValue, oldValue) {
									scope.$parent.$eval(attr.ngChange);
								});
							}
							function renderController() {
								$select.renderComplated = true;
								var selected, index;
								clearSelected();
								if (options.displayType == 'input') {
									if (controller.$modelValue)
										renderSelected();
								}
								else {
									if (options.multiple && angular.isArray(controller.$modelValue)) {
										selected = controller.$modelValue.map(function (value) {
											index = $select.$getIndex(value);
											if (angular.isDefined(index)) {
												$select.optionData[index].selected = true
												return $select.optionData[index].label
											}
											return false
										}).filter(angular.isDefined)
										selected = selected.join(options.seperator)
									} else {
										index = $select.$getIndex(controller.$viewValue);
										if (angular.isDefined(index)) {
											$select.optionData[index].selected = true
											selected = $select.optionData[index].label
										}
										else
											selected = false;
									}
									if (selected) {
										element.html(selected)
										if (!options.disableClear && !options.multiple) {
											var clrIcon = angular.element(clearIcon)
											clrIcon.one('click', function (evt) {
												evt.preventDefault();
												evt.stopPropagation();
												$timeout(function () {
													scope.$lastSelected && (scope.$lastSelected.selected = false);
													controller.$setViewValue(null);
													controller.$render()
												}, 0)

											});
											element.append(clrIcon)
										}
									}
									else
										element.html(options.placeholder)
								}
							}
							function renderSelected() {
								var current = element.find('li')
								angular.forEach(current, function (elm, key) {
									if (key < current.length - 1)
										elm.remove()
								})
								if (angular.isArray(controller.$modelValue)) {
									angular.forEach(controller.$modelValue, function (value, key) {
										var index = $select.$getIndex(value)
										if (index > -1) {
											$select.optionData[index].selected = true
											inputItem.before(renderItem($select.optionData[index], key));
										}
									})
								}
								else {
									var index = $select.$getIndex(controller.$modelValue)
									if (index > -1) {
										$select.optionData[index].selected = true
										inputItem.before(renderItem($select.optionData[index], controller.$modelValue));
									}
								}
								$select.$isShown &&
									$select.$applyPlacement();
							}
							function renderItem(item, key) {
								var li = angular.element('<li class="active"></li>')
								li.on('click', function (e) { e.preventDefault(), e.stopPropagation() })
								var closer = angular.element(options.clearIcon)
									.one('click', function (e) {
										e.preventDefault();
										e.stopPropagation();
										if (angular.isArray(controller.$modelValue)) {
											controller.$modelValue = controller.$modelValue.splice(key, 1);
										}
										else
											controller.$modelValue = null
										li.off()
										li.remove()
										scope.$apply(function () {
											item.selected = false;
											item.filtered = false;
										})
									});
								return li.append(angular.element('<a></a>').append(item.label).append(closer))
							}
							function highlightText(value) {
								setTimeout(function () {
									if (options.highlight && $target) {
										var items = $target.find('.option-label')
										if (items.length) {
											angular.forEach(items, function (val) {
												var el = angular.element(val);
												if (value)
													el.html(el.text().replace(new RegExp('(' + value + ')', 'gi'), '<span class="highlight">$1</span>'));
												else
													el.html(el.text());
											})
										}
									}
								}, 100)

							}
							function localFiler(newValue, oldValue) {
								if (!options.customFilter) {
									if (newValue) {
										$select.updateMatches($filter('filter')($select.optionData, scope.filterModel), isTagsInput);
									}
									else if (!newValue && oldValue)
										$select.updateMatches(undefined, isTagsInput)
								}
								else {
									if (!newValue && !oldValue)
										return;
									var i = 0
									$filter('filter')($select.optionData, function (obj) {
										if (isTagsInput && obj.selected)
											obj.filtered = true
										else {
											if (obj.label.search(new RegExp(newValue, "i")) < 0)
												obj.filtered = true
											else {
												obj.filtered = false;
												i++;
											}
										}
									})
									scope.$noResultFound = !i;
								}
								highlightText(newValue)
							}
							function remoteFiler(newValue, oldValue) {
								if (newValue) {
									scope.$remainingChar = options.minChar - newValue.length;
									scope.$noResultFound = false;
									if (scope.$remainingChar == 0 && scope.lastTerm != newValue)
										$select.loadRemote(newValue);
									else
										localFiler(newValue, oldValue);
								}
							}
							function buildUrl(term, isPost) {
								var url = options.urlPrefix || '';
								url += isPost ? options.postUrl ? options.postUrl : options.url : options.url;
								if (term) {
									if (scope.urlParams.length) {
										angular.forEach(scope.urlParams, function (value, index) {
											var param = getParam(value, index)
											if (options.isQuerystring) {
												url += index == 0 ? '?' : '&';
												url += param.param + '=' + param.value;
											}
											else {
												url += '/' + param.value;
											}
										})
									}
									if (options.isQuerystring) {
										url += scope.urlParams.length ? '&' : '?';
										url += 'term=' + term;
									}
									else {
										url += '/' + term;
									}
								}
								return url;
							}
							function getParam(value, index) {
								var param = { param: 'p' + index }
								if (angular.isObject(value))
									for (var key in value) {
										if (key == 0)
											param.param = value[0]
										if (key == 1) {
											param.value = value[1]
											break
										}
									}
								else
									param.value = value;
								return param;
							}
							function validateModel() {
								if (angular.isDefined(attr.required) || angular.isDefined(attr.ngRequired)) {
									controller.$setValidity("required", controller.$modelValue);
								}
								if (options.minRequired) {
									if (angular.isArray(controller.$modelValue))
										controller.$setValidity("min-required", controller.$modelValue.length >= options.minRequired);
								}
							}
							function clearSelected() {
								angular.forEach($select.optionData, function (item) {
									item.selected = false;
								})
							}
							return $select;
						}
						return SelectFactory;
					}
				];
			})
			.provider('$tagsInput', function () {
				var defaults = this.defaults = {
					maxLength: 10,
					typeClass: 'tagsInput',
					navClass: 'nav-mixed',
					prefixEvent: 'tagsInput',
					allowedChars: '[A-Za-z0-9ŞşIıĞğÜüÇçÖö ]',
					clearStrict: true,
					placeholder: 'type...',
					modelIsLabel: true,
					preventDublication: true,
					caseSensitive: false,
					maxTextLength: 30,
					minTextLength: 3
				};
				this.$get = [
					'$select',
					'$filter',
					function ($select, $filter) {
						function TagsInputFactory(element, controller, config, attr, targetEl) {
							if (config.directive != 'nqTagsInput') {
								return new $select(element, controller, config, attr, targetEl)
							}
							var options = angular.extend({}, defaults, config);
							options.trigger = false;
							var $tagsInput = new $select(element, controller, options, attr, targetEl);
							var init = $tagsInput.init, scope = $tagsInput.$scope;
							$tagsInput.init = function () {
								init();
								$tagsInput.searchInput.on('keypress', $tagsInput.$onKeyEnter)
								$tagsInput.searchInput.on('keypress', $tagsInput.$onKeyPress)
							};
							$tagsInput.$onKeyEnter = function (e) {
								if (e.keyCode === 13) {
									if (angular.isArray(controller.$modelValue) && !(controller.$modelValue.length < options.maxLength))
										return false;
									var label = scope.filterModel.label;
									if (label && label.length >= options.minTextLength) {
										if (label.length > options.maxTextLength)
											label = label.substr(0, label.length)
										var newOpt = { label: label, value: label };
										newOpt = $tagsInput.addOption(newOpt);
										if (!newOpt.selected)
											$tagsInput.select(newOpt);
										$tagsInput.searchInput.val('')
									}
								}
							};
							$tagsInput.$onKeyPress = function (e) {
								var c = String.fromCharCode(e.which)
								if (!(new RegExp('^' + options.allowedChars + '$').test(c)))
									return false;
							};
							attr.nqTagsInput && scope.$parent.$watch(attr.nqTagsInput, function (newValue, oldValue) {
								if (angular.isArray(newValue)) {
									angular.forEach(newValue, function (val, index) {
										if (angular.isObject(val)) {
											if (val.label || val.value) {
												var item = {
													label: val.label || val.value,
													value: val.value || val.label
												};
												$tagsInput.addOption(item);
												$tagsInput.changeOption('modelIsLabel', false)
											}
										}
										else {
											var item = {
												label: val,
												value: val
											};
											$tagsInput.addOption(item)
										}
									})
								}
							});
							scope.$parent.$watch(attr.ngModel, function (newValue, oldValue) {
								if (newValue) {
									controller.$setViewValue(newValue)
									$tagsInput.render();
								}
							});
							return $tagsInput;
						}
						return TagsInputFactory;
					}
				]
			})
		angular.forEach(['nqSelect', 'nqTagsInput'], function (directive) {
			selectApp.directive(directive, [
				'$compile',
				'$tagsInput',
				'$parseOptions',
				function ($compile, $tagsInput, $parseOptions) {
					return {
						restrict: 'EAC',
						scope: true,
						require: ['ngModel', directive],
						controller: function () {
						},
						link: function postLink(scope, element, attr, controllers) {

							var options = {
								$scope: scope
							},
								ngModel = controllers[0];

							if (directive == 'nqTagsInput') {
								options.displayType = 'input';
								options.multiple = true;
							}
							options.directive = directive;

							var targetEl = element;
							if (attr.ngOptions)
								options.grouped = attr.ngOptions.indexOf('group by') > -1;
							else if (element.is('select'))
								options.grouped = element.find('optgroup').length

							if (element.is('select') || element.is('input')) {
								targetEl.addClass('disable-animation')
								targetEl.css('display', 'none');
								buildElement()
							}
							else if (!angular.isDefined(attr.ngOptions)) {
								buildElement()
								targetEl.addClass('listbox');
								var scroller = angular.element('<div tabindex="-1" class="scrollable" role="listbox"></div>');

								scroller.append(targetEl.show());
								options.targetElement = angular.element('<div tabindex="-1" role="listbox" class="listbox-panel"></div>').append(scroller);
							}
							else if (attr.qoDisplayType == 'input') {
								buildElement();
							}
							var select = new $tagsInput(element, ngModel, options, attr, targetEl);
							controllers[1].addOption = select.addOption;
							controllers[1].changeOption = select.changeOption;
							controllers[1].select = select.select;
							ngModel.$render = select.render;
							scope.$on('$destroy', function () {
								select.destroy();
								options = null;
								select = null;
							});
							function buildElement() {
								if (options.displayType == 'input' || attr.qoDisplayType == 'input') {
									options.filterable = true;
									element = angular.element('<ul class="nav nav-pills select-render-nav form-control"></ul>');
									targetEl.hide()
								}
								else
									element = angular.element('<button type="button" class="btn form-control">Please select...</button>');
								targetEl.before(element);
							}
						}
					};
				}
			]);
		});

		selectApp.directive('selectOption', [
			function () {
				return {
					restrict: 'AC',
					scope: true,
					require: '?^nqSelect',
					link: function postLink(scope, element, attr, controller) {
						var itemkey, watcher, item = {};
						if (angular.isDefined(attr.ngRepeat))
							itemkey = attr.ngRepeat.split(' ')[0];
						else if (angular.isDefined(element.parent().attr('ng-repeat') || element.parent().attr('data-ng-repeat'))) {
							var parentattr = element.parent().attr('ng-repeat') || element.parent().attr('data-ng-repeat')
							if (parentattr)
								itemkey = parentattr.split(' ')[0];
						}
						watcher = itemkey + '.selected';
						if (controller) {
							scope.$watch(controller.changeOption, function (newValue, oldValue) {
								if (angular.isDefined(controller.changeOption))
									controller.changeOption('customFilter', true);
							});
							element.addClass('select-option')
							element.attr('tabindex', -1)
							element.attr('role', 'option')
							item.label = scope.$eval(attr.optionLabel) || attr.optionLabel;
							item.value = scope.$eval(attr.optionValue) || attr.optionValue || item.label;
							scope.$watch(controller.changeOption, function (newValue, oldValue) {
								if (angular.isDefined(controller.addOption))
									scope._selectOption = controller.addOption(item);
							});

							watcher = '_selectOption.selected';
							element.on('click', function () {
								controller.select(scope._selectOption)
							})
							scope.$watch('_selectOption.filtered', function (newValue, oldValue) {
								newValue ? element.hide() : element.show()
							});
						}
						scope.$watch(watcher, function (newValue, oldValue) {
							newValue ? element.addClass('selected') : element.removeClass('selected')
						});
						scope.$on('$destroy', function () {
							element && element.remove();
						});

					}
				};
			}
		])
		selectApp.filter('groupOption', ['$filter', function ($filter) {
			return function (array) {
				if (!array || !array.length)
					return []
				var newArray = [];
				angular.forEach(array, function (value) {
					if (value.group)
						addToGroup(value);
					else
						newArray.push(value)
				})
				function addToGroup(value) {
					var group = $filter('filter')(newArray, function (gr) {
						if (angular.isObject(value.group)) {
							return gr.label === value.group.label;
						}
						else
							return gr.label == value
					});
					if (group.length) {
						group = group[0]
						group.items.push(value)
					}
					else {
						if (angular.isObject(value.group))
							group = angular.copy(value.group);
						else
							group = { label: value };
						group.items = []
						group.items.push(value)
						newArray.push(group)
					}
				}
				return newArray;
			};
		}]);
	}(window, window.angular);
'use strict';
angular.module('ngQuantum.slider', ['ngQuantum.services.mouse', 'ngQuantum.services.helpers'])
	.provider('$slider', function () {
		var defaults = this.defaults = {
			keyboard: true,
			decimalPlace: 0,
			step: 1,
			min: 0,
			max: 100,
			doubleThumb: false,
			diff: 10,
			size: false,
			sizeClass: false,
			showTooltip: true,
			tooltipVisible: false,
			showRuller: false,
			showLabel: false,
			tickSize: 10,
			valuePrefix: false,
			valueSuffix: false,
			formatValue: false,
			direction: 'horizontal',
			theme: false,
			thumbClass: false
		};
		this.$get = ['$rootScope', '$document', '$mouse', '$parse',
			function ($rootScope, $document, $mouse, $parse) {
				function Factory(element, config) {
					var $slider = {}, template, track, selection, thumb, thumb2, sizes, body = angular.element('body');

					var options = angular.extend({}, defaults, config);
					if (defaults.formatValue) {
						options.callValueFunction = defaults.formatValue;
					}
					if (options.formatValue) {
						options.formatValue = $parse(options.formatValue);
						options.callValueFunction = false;
					}
					if (options.formatValue == false)
						options.callValueFunction = false;
					var scope = $slider.$scope = options.$scope && options.$scope.$new() || $rootScope.$new();
					$slider.lastOffset = 0;
					$slider.lastOffset2 = 0;
					$slider.init = function () {
						getTemplate();
						template.addClass('slider-' + (options.direction == 'vertical' ? 'vertical' : 'horizontal'));
						if (options.size) {
							options.direction == 'vertical' ? template.height(options.size) : template.width(options.size)
						}
						options.sizeClass && template.addClass('slider-' + options.sizeClass)
						findSizes();
						bindMouse();
						var titipclass = 'titip-' + (options.direction == 'vertical' ? 'left' : 'top') + ' titip-sm';
						if (options.tooltipVisible) {
							titipclass += ' titip-sm titip-active';
						}
						if (options.showTooltip || options.tooltipVisible) {
							thumb.addClass(titipclass);
							thumb2 && thumb2.addClass(titipclass);
						}
						if (options.doubleThumb)
							options.direction == 'vertical' ? ($slider.lastOffset2 = sizes.trh) : ($slider.lastOffset2 = sizes.trw);
						$slider.setValues();
						if (options.showRuller || options.showLabel)
							buildRuller();


					}
					$slider.setValues = function (value) {
						if (!value) {
							applyValue();
							value = scope.values;
						}
						if (options.doubleThumb) {
							if (!angular.isArray(value)) {
								value = [value, options.max]
							}
							var v1 = (value[0] - options.min) / sizes.stepRate;
							var v2 = (value[1] - options.min) / sizes.stepRate;
							if (options.direction == 'vertical') {
								v1 = v1 > sizes.trh ? sizes.trh : v1 < 0 ? 0 : v1;
								bottomSlide(v1)
								v2 = v2 > sizes.trh ? sizes.trh : v2 < 0 ? 0 : v2;
								topSlide(v2)
							}
							else {
								v1 = v1 > sizes.trw ? sizes.trw : v1 < 0 ? 0 : v1;
								leftSlide(v1)
								v2 = v2 > sizes.trw ? sizes.trw : v2 < 0 ? 0 : v2;
								rightSlide(v2)
							}
						} else {
							var v = (value - options.min) / sizes.stepRate;
							if (options.direction == 'vertical') {
								v = v > sizes.trh ? sizes.trh : v < 0 ? 0 : v;
								bottomSlide(v)
							}
							else {
								v = v > sizes.trw ? sizes.trw : v < 0 ? 0 : v;
								leftSlide(v)
							}
						}
						scope.$$postDigest(applyValue);
					}
					$slider.toggleDisable = function (disbled) {
						if (disbled) {
							template.addClass('slider-disabled')
							unbindMouse();
						}
						else {
							template.removeClass('slider-disabled');
							unbindMouse();
							bindMouse();
						}

					}
					$slider.destroy = function () {
						unbindMouse();
						scope.$destroy();
					}
					function applyValue() {
						if (options.doubleThumb)
							scope.values = [$slider.value0 || options.min, $slider.value1 || options.max];
						else
							scope.values = $slider.value0 || options.min;
					}
					function bindMouse() {
						$mouse.down(track, function (event) {
							if (event.target == track[0] || event.target == selection[0]) {
								$slider.eventNo = 0;
								slideThumb(event);
							}
						})
						$mouse.down(thumb, function (event) {
							$slider.eventNo = 1;
							$mouse.move($document, slideThumb);
							$mouse.up(body, documentUp)
						})
						thumb2 &&
							$mouse.down(thumb2, function (event) {
								$slider.eventNo = 2;
								$mouse.move($document, slideThumb)
								$mouse.up(body, documentUp)
							})

					}
					function unbindMouse() {
						$mouse.offDown(track)
						$mouse.offDown(thumb);
						thumb2 && $mouse.offDown(thumb2);
						$mouse.offMove($document, slideThumb);
						$mouse.offUp(body, documentUp)
					}
					function documentUp(event) {
						$mouse.offMove($document, slideThumb)
						if (options.showTooltip && !options.tooltipVisible) {
							thumb.removeClass('titip-active');
							thumb2 && thumb2.removeClass('titip-active');
						}
						angular.element('body').removeClass('unselectable');
						$mouse.offUp(body, documentUp);

					}
					function slideThumb(event) {
						event.preventDefault();
						event.stopPropagation();
						angular.element('body').addClass('unselectable')
						if (!sizes)
							findSizes();
						if (options.showTooltip && !options.tooltipVisible) {
							thumb.addClass('titip-active');
							thumb2 && thumb2.addClass('titip-active');
						}
						options.direction == 'vertical' ? slideVertical(event) : slideHorizontal(event);
						scope.$apply(applyValue)

					}
					function slideVertical(event) {
						var thumNo = 1;
						var x = $mouse.relativeY(event, template);
						x = sizes.trh - x;
						x = x > sizes.trh ? sizes.trh : x < 0 ? 0 : x;
						var val = (Math.abs(x - $slider.lastOffset) >= sizes.stepSize) || x == 0 || x == sizes.trh;
						if ((options.doubleThumb && $slider.eventNo == 2) ||
							(options.doubleThumb && $slider.eventNo == 0
								&& ((x > $slider.lastOffset2) || (Math.abs(x - $slider.lastOffset) > Math.abs(x - $slider.lastOffset2))))) {
							val = (Math.abs(x - $slider.lastOffset2) >= sizes.stepSize) || x == 0 || x == sizes.trh;
							thumNo = 2;
						}
						if (sizes.stepSize < 0 || val) {
							thumNo == 2 ? topSlide(x) : bottomSlide(x);
						}
					}
					function slideHorizontal(event) {
						var thumNo = 1;
						var x = $mouse.relativeX(event, template);
						x = x > sizes.trw ? sizes.trw : x < 0 ? 0 : x;
						var val = (Math.abs(x - $slider.lastOffset) >= sizes.stepSize) || x == 0 || x == sizes.trw;
						if ((options.doubleThumb && $slider.eventNo == 2) ||
							(options.doubleThumb && $slider.eventNo == 0
								&& ((x > $slider.lastOffset2) || (Math.abs(x - $slider.lastOffset) > Math.abs(x - $slider.lastOffset2))))) {
							val = (Math.abs(x - $slider.lastOffset2) >= sizes.stepSize) || x == 0 || x == sizes.trw;
							thumNo = 2;
						}
						if (sizes.stepSize < 0 || val) {
							thumNo == 2 ? rightSlide(x) : leftSlide(x);
						}
					}
					function leftSlide(x) {
						if (sizes.diffPixel && ((x + sizes.diffPixel) > $slider.lastOffset2))
							x = $slider.lastOffset2 - sizes.diffPixel + 1;
						var value = getValue(x);
						$slider.lastOffset = x;
						thumb.css({ left: x });
						options.showTooltip && thumb.attr('data-title', getValueFormat(value));
						if (options.doubleThumb) {
							var r = $slider.lastOffset2 > x ? (sizes.trw - $slider.lastOffset2) : 0;
							selection.css({ left: x, right: r });
						}
						else
							selection.css({ left: 0, right: sizes.trw - x });
						$slider.value0 = value;

					}
					function rightSlide(x) {
						if (sizes.diffPixel && ((x - sizes.diffPixel) < $slider.lastOffset))
							x = $slider.lastOffset + sizes.diffPixel;
						var value = getValue(x);
						$slider.lastOffset2 = x;
						thumb2.css({ left: x });
						options.showTooltip && thumb2.attr('data-title', getValueFormat(value));
						var l = $slider.lastOffset > 0 ? $slider.lastOffset : 0;
						selection.css({ right: sizes.trw - x, left: l });
						$slider.value1 = value;

					}

					function bottomSlide(x) {
						if (sizes.diffPixel && ((x + sizes.diffPixel) > $slider.lastOffset2))
							x = $slider.lastOffset2 - sizes.diffPixel + 1;
						var value = getValue(x);
						$slider.lastOffset = x;
						thumb.css({ bottom: x });
						options.showTooltip && thumb.attr('data-title', getValueFormat(value));
						if (options.doubleThumb) {
							var t = $slider.lastOffset2 > x ? (sizes.trh - $slider.lastOffset2) : 0;
							selection.css({ bottom: x, top: t });
						}
						else
							selection.css({ bottom: 0, top: sizes.trh - x });
						$slider.value0 = value;

					}
					function topSlide(x) {
						if (sizes.diffPixel && ((x - sizes.diffPixel) < $slider.lastOffset))
							x = $slider.lastOffset + sizes.diffPixel;
						var value = getValue(x);
						$slider.lastOffset2 = x;
						thumb2.css({ bottom: x });
						options.showTooltip && thumb2.attr('data-title', getValueFormat(value));
						var b = $slider.lastOffset > 0 ? $slider.lastOffset : 0;
						selection.css({ bottom: b, top: sizes.trh - x });
						$slider.value1 = value;

					}
					function getValue(val) {
						if (!options.decimalPlace)
							return Math.floor(val * sizes.stepRate) + parseFloat(options.min);
						return parseFloat(Math.round(((val * sizes.stepRate) + parseFloat(options.min)) * 100) / 100).toFixed(options.decimalPlace)
					}
					function getValueFormat(val) {
						if (options.callValueFunction)
							return options.callValueFunction.call(null, val);
						else if (options.formatValue)
							return options.callValueFunction(scope, { $value: val });
						else {
							options.valuePrefix && (val = options.valuePrefix + val);
							options.valueSuffix && (val += options.valueSuffix);
							return val;
						}
					}
					function findSizes() {
						sizes = {
							trw: track.width(),
							thh: thumb.outerHeight(),
							thw: thumb.outerWidth(),
							trh: track.height()
						}
						var margins = {};
						if (options.direction == 'vertical') {
							margins['margin-bottom'] = -(sizes.thh / 2);
							margins['margin-left'] = -((sizes.thw - sizes.trw) / 2);
						}
						else {
							margins['margin-left'] = -(sizes.thw / 2);
							margins['margin-top'] = -((sizes.thh - sizes.trh) / 2);
						}
						thumb.css(margins)
						thumb2 && thumb2.css(margins)
						findStep();
					}
					function findStep() {
						var diff = (options.max - options.min) / options.step;
						if (options.direction == 'vertical') {
							sizes.stepRate = diff / sizes.trh;
							sizes.stepSize = sizes.trh / diff;
						} else {
							sizes.stepRate = diff / sizes.trw;
							sizes.stepSize = sizes.trw / diff;
						}
						options.diff && options.doubleThumb && (sizes.diffPixel = Math.round(sizes.stepSize * options.diff));

					}
					function getTemplate() {
						template = angular.element('<div class="range-slider"></div>').insertBefore(element).append(element)
						track = angular.element('<div class="slider-track"></div>').appendTo(template);
						selection = angular.element('<div class="slider-selection"></div>').appendTo(track);
						thumb = angular.element('<div class="slider-thumb"></div>').appendTo(track);
						options.theme && template.addClass('slider-' + options.theme)
						options.thumbClass && thumb.addClass(options.thumbClass)
						if (options.doubleThumb) {
							thumb2 = angular.element('<div class="slider-thumb"></div>').appendTo(track);
							options.thumbClass && thumb2.addClass(options.thumbClass)
						}

					}
					function buildRuller() {
						var ruller = angular.element('<div class="slider-ruller"></div>').appendTo(template);
						if (options.showRuller) {
							var ticks = angular.element('<div class="slider-ticks"></div>').appendTo(ruller);
							if (options.tickSize > 20)
								options.tickSize = 20;
							if (options.tickSize > 0)
								for (var i = 0; i < options.tickSize - 1; i++) {
									ticks.append('<span  class="slider-tick"></span>')
								}
						}
						if (options.showLabel)
							ruller.append('<div class="slider-values"><div class="values-min">' + getValueFormat(options.min) + '</div><div class="values-max">' + getValueFormat(options.max) + '</div></div>');

					}
					$slider.init();
					return $slider;
				}
				return Factory;
			}
		];
	})
	.directive('nqSlider', ['$slider', '$helpers', function ($slider, $helpers) {
		return {
			restrict: 'AC',
			require: 'ngModel',
			link: function postLink(scope, element, attr, controller) {
				var options = {
					$scope: scope
				}
				var keys = ['disabled', 'keyboard', 'decimalPlace', 'step', 'min', 'max', 'doubleThumb', 'showLabel',
					'diff', 'size', 'sizeClass', 'showRuller', 'direction', 'theme', 'thumbClass', 'valuePrefix', 'valueSuffix', 'formatValue']
				angular.forEach(keys,
					function (key) {
						if (angular.isDefined(attr[key])) {
							options[key] = $helpers.parseConstant(attr[key])
						}

					});
				var slider = new $slider(element, options)
				scope.$watch(attr.ngModel, function (newVal, oldVal) {
					if (newVal) {
						if (newVal != slider.$scope.values) {
							slider.setValues(newVal);
						}

					}
				})
				attr.$observe('disabled', function (newVal, oldVal) {
					if (newVal) {
						slider.toggleDisable(true);
					}
					else if (oldVal) {
						slider.toggleDisable(false);
					}
				})
				slider.$scope.$watch('values', function (newVal, oldVal) {
					if (newVal && (newVal !== oldVal)) {
						controller.$setViewValue(newVal);
					}
				})
				scope.$on('$destroy', function () {
					slider.destroy();
					slider = null

				})
			}
		};
	}])
'use strict';
angular.module('ngQuantum.switchButton', ['ngQuantum.services.helpers'])
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('switch/switchbutton.tpl.html',
			'<div class="btn-group btn-switch">'
			+ '<label class="btn" ng-class="$buttonTheme"><span ng-class="{visibleswitch:$checked}" ng-bind-html="$trueLabel"></span><span class="switch-bg" ng-class="{visibleswitch:!$checked}"></span><span class="switch-label" ng-class="{visibleswitch:!$checked}" ng-bind-html="$labelText"></span></label>'
			+ '<label class="btn" ng-class="$buttonTheme"><span ng-class="{visibleswitch:!$checked}" ng-bind-html="$falseLabel"></span><span class="switch-bg" ng-class="{visibleswitch:$checked}"></span><span class="switch-label" ng-class="{visibleswitch:$checked}" ng-bind-html="$labelText"></span></label>'
			+ '</div>'
		)
	}])
	.provider('$switchButton', function () {
		var defaults = this.defaults = {
			trueLabel: 'ON',
			falseLabel: 'OFF',
			trueValue: true,
			falseValue: false,
			labelText: '&nbsp;',
			effect: 'slide-left',
			theme: 'default',
			btnSize: false
		};
		this.$get = function () {
			return { defaults: defaults };
		};
	})
	.directive('nqSwitchButton', ['$switchButton', '$helpers', function ($switchButton, $helpers) {
		return {
			restrict: 'AC',
			scope: {},
			templateUrl: 'switch/switchbutton.tpl.html',
			require: 'ngModel',
			link: function postLink(scope, element, attr, controller) {
				var button = element.children();
				element.after(button);
				element.hide();
				var options = angular.extend({}, $switchButton.defaults);
				angular.forEach(['theme', 'effect', 'btnSize'], function (key) {
					if (angular.isDefined(attr[key])) {
						options[key] = attr[key];
					}
				});
				angular.forEach(['trueLabel', 'falseLabel', 'labelText'], function (key) {
					if (angular.isDefined(attr[key])) {
						options[key] = $helpers.parseConstant(attr[key])
					}
					scope['$' + key] = options[key];
				});
				options.effect && button.addClass(options.effect);
				!options.theme && (options.theme == 'default')
				if (options.theme) {
					var themes = options.theme.split(','), newThemes = '';
					for (var i = 0; i < themes.length; i++)
						newThemes += 'btn-' + themes[i] + ' ';
					scope.$$postDigest(function () {
						scope.$buttonTheme = newThemes;
					});
				}

				options.btnSize && button.addClass('btn-group-' + options.btnSize);
				var trueValue = options.trueValue || true, falseValue = options.falseValue || false;
				angular.isDefined(attr.ngTrueValue) && (trueValue = attr.ngTrueValue);
				angular.isDefined(attr.ngFalseValue) && (trueValue = attr.ngFalseValue);


				scope.$parent.$watch(attr.ngModel, function (newVal, oldVal) {
					if (newVal == trueValue && !scope.$checked) {
						scope.$checked = true;
					}
					else if (newVal == falseValue && scope.$checked) {
						scope.$checked = false;
					}
				})
				button.on('click', function (e) {
					if (scope.$disabled) {
						e.preventDefault();
						return false;
					}
					scope.$apply(function () {
						attr.$set('checked', !scope.$checked)
					});
				})
				attr.$observe('checked', function (newVal, oldVal) {
					scope.$checked = newVal;
					if (newVal)
						controller.$setViewValue(trueValue);
					else
						controller.$setViewValue(falseValue);
				})
				attr.$observe('disabled', function (newVal, oldVal) {
					scope.$disabled = newVal;
					if (scope.$disabled)
						button.addClass('btn-disabled')
					else
						button.removeClass('btn-disabled')
				})
				scope.$on('$destroy', function () {
					button.off('click');
					button = null;
					options = null;
				})
			}
		};
	}])
'use strict';
angular.module('ngQuantum.tabset', ['ngQuantum.services.helpers'])
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('tabs/tabset.tpl.html',
			'<div class="tab-container {{theme}}">'
			+ '<ul class="nav {{navClasses}}" nav-placement="{{placement}}">'
			+ '<li ng-repeat="pane in panes | orderBy:$paneindex" ng-class="{active: pane.active, disabled: pane.disabled}">'
			+ '<a role="button" tabindex="0" tab-heading-transclude="pane">{{pane.heading}}</a>'
			+ '</li>'
			+ '</ul>'
			+ '<div class="tab-content clearfix" ng-transclude></div>'
			+ '</div>'
		);
		$templateCache.put('tabs/tabset.responsive.tpl.html',
			'<div class="tab-container {{theme}}">'
			+ '<ul class="nav {{navClasses}}" nav-placement="{{placement}}">'
			+ '<li ng-repeat="pane in panes" ng-show="!pane.stored"  ng-class="{active: pane.active, disabled: pane.disabled}">'
			+ '<a role="button" tabindex="0" tab-heading-transclude="pane">{{pane.heading}}</a>'
			+ '</li>'
			+ '<li ng-show="showMore">'
			+ '<a role="button" tabindex="0" nq-dropdown="" class="dropdown-toggle" data-placement="{{ddPlacement}}">More</a>'
			+ '<ul class="dropdown-menu">'
			+ '<li ng-repeat="pane in panes | filter:{stored:true}" ng-class="{active: pane.active, disabled: pane.disabled}">'
			+ '<a role="button" tabindex="0" ng-click="pane.select()" ng-bind-html="pane.htmlString"></a>'
			+ '</li>'
			+ '</ul>'
			+ '</li>'
			+ '</ul>'
			+ '<div class="tab-content" ng-transclude></div>'
			+ '</div>'
		);
	}])
	.provider('$tabset', function () {
		var defaults = this.defaults = {
			effect: 'slide-right-left',
			type: 'tabs',
			speed: 'fastest',
			placement: 'top',
			justified: false,
			prefixEvent: 'tabs',
			directive: 'nqTab',
			instanceName: 'tabs',
			fireEmit: false,
			fireBroadcast: false,
			keyboard: false,
			theme: false,
			trigger: 'click',
			responsive: true,
			delay: 0
		};
		this.$get = ['$timeout', '$filter', '$compile', '$sce', '$animate',
			function ($timeout, $filter, $compile, $sce, $animate) {
				function TabFactory($scope, config) {

					var $tabset = {},
						options = $tabset.$options = angular.extend({}, defaults, config),

						panes = $tabset.panes = $scope.panes = [];
					var nc = 'nav-' + options.type;
					if (options.justified)
						nc = nc + ' nav-justified'
					else if (/right|left/.test(options.placement)) {
						nc = nc + ' nav-stacked'
						options.responsive = false;
					}
					$scope.ddPlacement = 'bottom-right'
					$scope.navClasses = nc
					$scope.theme = (options.theme && 'nav-' + options.theme) + ' tab-' + options.placement;
					$scope.placement = options.placement;
					if (options.placement == "bottom")
						$scope.ddPlacement = 'top-right'
					$tabset.select = function (selectedPane) {
						angular.forEach(panes, function (pane) {
							if (pane.active && pane !== selectedPane) {
								pane.active = false;
								pane.activeClasses = '';
								pane.onDeselect();
							}
						});
						selectedPane.active = true;
						selectedPane.onSelect();
					};

					$tabset.addPane = function (pane) {
						panes.push(pane);
						if (panes.length === 1) {
							pane.active = true;
						} else if (pane.active) {
							$tabset.select(pane);
						}
						$tabset.lastStoredIndex++;
					};
					$tabset.removePane = function (pane) {
						var index = panes.indexOf(pane);
						if (pane.active && panes.length > 1) {
							var newActiveIndex = index == panes.length - 1 ? index - 1 : index + 1;
							$tabset.select(panes[newActiveIndex]);
						}
						panes.splice(index, 1);
					};

					$tabset.panesWidth = 0;
					$tabset.lastStoredIndex = -1;
					return $tabset;
				}
				return TabFactory;
			}
		];
	})
	.directive('nqTabset', ['$tabset', '$compile', '$timeout', '$helpers', function ($tabset, $compile, $timeout, $helpers) {
		return {
			restrict: 'EA',
			transclude: true,
			replace: true,
			scope: {},
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.template))
					return attr.template;
				if (attr.responsive && !/right|left/.test(attr.placement))
					return 'tabs/tabset.responsive.tpl.html';
				return 'tabs/tabset.tpl.html';
			},
			controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
				var that = this;
				var options = {};
				angular.forEach(['theme', 'justified', 'effect', 'type', 'speed', 'placement', 'keyboard', 'trigger', 'responsive'],
					function (key) {
						angular.isDefined($attrs[key]) && (options[key] = $helpers.parseConstant($attrs[key]))
					})
				var ctrl = new $tabset($scope, options);
				that = angular.extend(that, ctrl);
				if ($attrs.tabsetModel)
					$scope.$parent[$attrs.tabsetModel] = that;
				return that;
			}],

			link: function postLink(scope, elm, attrs, controller, transcludeFn) {
				attrs.nqTabset && scope.$parent.$watch(attrs.nqTabset, function (newValue, oldValue) {
					var content = elm.find('.tab-content');
					if (newValue && newValue.length && content.length) {
						for (var j = 0; j < newValue.length; j++) {
							var paneelm = angular.element('<div data-nq-tab=""></div>').append('<span data-tab-heading="">' + newValue[j].heading + '</span>')
								.append(newValue[j].content)
							content.append(paneelm)
							$compile(paneelm)(scope)
						}
					}
				}, true);
				if (controller.$options.responsive) {
					scope.$watch(function () { return elm.width(); }, function (newValue, oldValue) {
						setTimeout(function () {
							scope.$apply(function () {
								responsiveDesign(elm.innerWidth() - 90, newValue)
							});
						}, 0)
					});

				}
				function responsiveDesign(value, oldValue) {
					!oldValue && (oldValue = 0)
					!value && (value = 0)
					var dif = Math.abs(controller.panesWidth - value)
					if (!value || !controller.panes.length || dif < 10)
						return;
					if (value < controller.panesWidth) {
						if (controller.panes.length <= controller.lastStoredIndex || controller.lastStoredIndex == -1)
							controller.lastStoredIndex = controller.panes.length - 1;
						while (value < controller.panesWidth && controller.lastStoredIndex > 0) {
							var p = controller.panes[controller.lastStoredIndex];

							if (!p.stored) {
								controller.panesWidth -= p.widht;
								p.stored = true;
								scope.showMore = true;
							}
							controller.lastStoredIndex--
						}
					}
					else if (value > controller.panesWidth) {
						while (value > controller.panesWidth && controller.panes.length > controller.lastStoredIndex) {
							var p = controller.panes[controller.lastStoredIndex];

							if (p && p.stored == true) {
								controller.panesWidth += p.widht;
								p.stored = false;
							}

							controller.lastStoredIndex++;
							(controller.panes.length == controller.lastStoredIndex) && (scope.showMore = false)
						}
					}
				}

			}
		};
	}])
	.directive('nqTab', ['$parse', '$timeout', function ($parse, $timeout) {
		return {
			require: '^nqTabset',
			restrict: 'EA',
			replace: true,
			template: '<div class="tab-pane clearfix" tab-content-transclude=""></div>',
			transclude: true,
			scope: {
				heading: '@',
				onSelect: '&select',
				onDeselect: '&deselect'
			},
			controller: function () {
			},
			compile: function (elm, attrs, transclude) {
				return function postLink(scope, elm, attrs, controller) {
					scope.effect = controller.$options.effect;
					scope.speed = controller.$options.speed;
					angular.isDefined(attrs.effect) && (scope.effect = attrs.effect)
					angular.isDefined(attrs.speed) && (scope.effect = attrs.speed)
					if (angular.isDefined(attrs.active)) {
						scope.$$postDigest(function () {
							scope.select()
						});
					}
					scope.$watch('active', function (active) {
						if (active) {
							controller.select(scope);
						}
					});

					scope.disabled = false;
					if (attrs.disabled) {
						scope.$parent.$watch($parse(attrs.disabled), function (value) {
							scope.disabled = !!value;
						});
					}

					scope.select = function () {
						if (!scope.disabled) {
							scope.active = true;
						}
					};
					scope.$paneindex = elm.index() || scope.$index;;
					controller.addPane(scope);
					scope.$on('$destroy', function () {
						controller.removePane(scope);
					});

					$timeout(function () {
						scope.$transcludeFn = transclude;
					}, 0)

				};
			}
		};
	}])
	.directive('tabHeadingTransclude', ['$compile', function ($compile) {
		return {
			restrict: 'A',
			require: '^nqTabset',
			link: function (scope, elm, attrs, controller) {
				var pane = scope.$eval(attrs.tabHeadingTransclude);
				scope.$watch(function () { return pane.headingElement }, function (heading) {
					if (heading) {
						elm.html($compile(angular.element(heading))(scope));
						pane.widht = elm.parent().outerWidth(true);

					}
					else
						pane.widht = elm.parent().outerWidth(true);
					if (pane.oldWidth)
						controller.panesWidth -= pane.oldWidth;
					pane.oldWidth = pane.widht
					controller.panesWidth += pane.widht;
					pane.htmlString = elm.html();
				});
				elm.on('click', function (evt) {
					evt.preventDefault();
					evt.stopPropagation();
					console.log(pane)
					if (pane.active) return;

					scope.$apply(function () {
						pane.select();
					})
				})
			}
		};
	}])
	.directive('navPlacement', [function () {
		return {
			restrict: 'A',
			require: '^nqTabset',
			link: function (scope, elm, attrs, controller) {
				attrs.$observe('navPlacement', function (value) {
					if (/bottom|right/.test(value)) {
						elm.parent().append(elm)
					}
				})
			}
		};
	}])

	.directive('tabContentTransclude', ['$animate', '$timeout', function ($animate, $timeout) {
		return {
			restrict: 'A',
			require: '^nqTab',
			link: function (scope, elm, attrs, controller) {
				scope.$watch('$transcludeFn', function (value) {
					value && scope.$transcludeFn(scope.$parent, function (contents) {
						angular.forEach(contents, function (node, i) {
							if (isTabHeading(node)) {
								scope.headingElement = node;
							} else {
								elm.append(node);
							}
						});

					});
				});
				scope.$watch('active', function (value) {
					value ? show() : hide();
				});
				function show() {
					elm.css('display', 'block');
					elm.css('visibility', 'visible');
					if (scope.effect) {
						elm.addClass(scope.speed);
						var content = elm.closest('.tab-content');
						content.css('overflow', 'hidden');
						$animate.addClass(elm, scope.effect).then(function () {
							content.css('overflow', '')
						});
					}

				}
				function hide() {
					elm.css('visibility', 'hidden');
					elm.css('display', 'none');
					if (scope.effect) {
						elm.removeClass(scope.speed)
						elm.removeClass(scope.effect)
					}
				}
			}
		};
		function isTabHeading(node) {
			return node.tagName && (
				node.hasAttribute('tab-heading') ||
				node.hasAttribute('data-tab-heading') ||
				node.tagName.toLowerCase() === 'tab-heading' ||
				node.tagName.toLowerCase() === 'data-tab-heading'
			);
		}
	}]);

'use strict';
angular.module('ngQuantum.tooltip', ['ngQuantum.popMaster'])
	.run(['$templateCache', function ($templateCache) {
		'use strict';

		$templateCache.put('tooltip/tooltip.tpl.html',
			"<div class=\"tooltip in\" ng-show=\"title\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\" ng-bind=\"title\"></div></div>"
		);

	}])
	.provider('$tooltip', function () {
		this.$get = [
			'$sce',
			'$rootScope',
			'$popMaster', '$helpers',
			function ($sce, $rootScope, $popMaster, $helpers) {
				var defaults = this.defaults = {
					title: false,
					template: 'tooltip/tooltip.tpl.html',
					directive: 'nqTooltip',
					typeClass: 'tooltip',
					prefixEvent: 'tooltip',
					container: 'body',
					displayReflow: true,
					autoDestroy: false,
					forceHide: true,
					clearExists: false,
				}
				function TooltipFactory(element, config, attr) {
					var $tooltip = {};
					config = $helpers.parseOptions(attr, config);
					var options = config = angular.extend({}, defaults, config);

					$tooltip = new $popMaster(element, options);
					var scope = $tooltip.$scope
					options = $tooltip.$options = $helpers.observeOptions(attr, $tooltip.$options);
					if (options.title) {
						scope.title = options.title;
					}

					if (attr) {
						attr.qsTitle && (scope.title = attr.qsTitle);
						attr.$$observers && attr.$$observers.qsTitle && attr.$observe('qsTitle', function (newValue, oldValue) {
							scope.title = newValue;
							angular.isDefined(oldValue) && $tooltip.$applyPlacement();
						});
					}
					scope.$on('$destroy', function () {
						$tooltip && $tooltip.destroy();
						$tooltip = null;
					});
					return $tooltip;
				}
				return TooltipFactory;
			}
		];
	})
	.directive('nqTooltip', [
		'$tooltip',
		function ($tooltip) {
			return {
				restrict: 'EAC',
				link: function postLink(scope, element, attr, transclusion) {
					var options = {
						$scope: scope.$new()
					};
					if (element[0].tagName.toLowerCase() == 'input')
						options.isInput = true;
					var tooltip = $tooltip(element, options, attr);
					scope.$on('$destroy', function () {
						options.$scope.$destroy();
					})
				}
			};
		}
	]);

'use strict';
angular.module('ngQuantum.pageable.blocker', [])
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('pageable/blocker.tpl.html',
			'<div class="pageable-spinner"></div>'
		);
	}])
	.directive('nqPageableBlocker', ['$timeout', function ($timeout) {
		return {
			restrict: 'A',
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return 'pageable/blocker.tpl.html'
			},
			require: '^nqPageable',
			link: function (scope, element, attr, controller) {
				var timeout = attr.timeout && parseInt(attr.timeout) || 100;
				element.addClass("pageable-blocker");
				scope.$watch('$pageableBusy', function (newVal, oldVal) {
					if (newVal) {
						element.show();
					}
					else $timeout(function () {
						element.hide();
					}, timeout)

				})

			}
		};
	}]);
(function (window, angular) {
	'use strict';
	var pApp = angular.module('ngQuantum.pageable.directives', ['ngQuantum.pageable.factory']);
	pApp.directive('nqPageable', ['$pageable', function ($pageable) {
		return {
			restrict: 'EA',
			require: 'nqPageable',
			scope: true,
			controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
				var that = this;
				var options = {
					$scope: $scope
				};
				$element.addClass('pageable-container');
				$element.css('position', 'relative');
				that = angular.extend(that, new $pageable($element, options, $attrs));
				that.$container = $element;
				$scope.$watch($attrs.nqPageable, function (newVal, oldVal) {
					that.setModelData(newVal);
				})
				if (angular.isDefined($attrs.qoAlias) && angular.isString($attrs.qoAlias)) {
					$scope.$parent[$attrs.qoAlias] = that;

				}
				return that;
			}]
		};
	}])
	angular.forEach(['pageableRepeat', 'pageableRepeatStart', 'pageableRepeatEnd'], function (directive, dIndex) {
		pApp.directive(directive, ['$compile', function ($compile) {
			return {
				require: '^nqPageable',
				restrict: 'EA',
				terminal: true,
				scope: false,
				priority: 1000,
				compile: function (tElm, tAttrs, transclude) {
					var repeatString = tAttrs.pageableRepeat;
					var tagName = tElm[0].tagName.toLowerCase();
					if (dIndex < 2) {
						tElm.removeAttr('pageable-repeat');
						tElm.removeAttr('data-pageable-repeat');
						tElm.removeAttr('pageable-repeat-start');
						tElm.removeAttr('data-pageable-repeat-start');
						var arrkey = repeatString.substr(repeatString.indexOf("in"), repeatString.length).split(' ')[1].split('=')[0];
						var replace = repeatString.replace(arrkey.trim(), '$currentRows');
						var rowField = repeatString.split(' ')[0];
						if (repeatString.indexOf("track") < 0)
							replace += ' track by  $index';
						var repeatAttr = dIndex == 0 ? 'ng-repeat' : 'ng-repeat-start'
						tElm.attr(repeatAttr, replace);
						tElm.addClass('pageable-item')
					} else {
						tElm.removeAttr('pageable-repeat-end');
						tElm.removeAttr('data-pageable-repeat-end');
						var attEnd = document.createAttribute("ng-repeat-end");
						tElm[0].setAttributeNode(attEnd);
					}


					return function postLink(scope, element, attr, controller) {
						if (controller.$options.effect)
							element.addClass(controller.$options.effect).addClass(controller.$options.speed);

						$compile(element)(scope)
						scope.$$postDigest(function () {
							controller.rowField = rowField;
							if (tagName == 'tr') {
								controller.tableElement = element.closest('table');
							}
							controller.shellElement = element.parent();
							controller.elementTag = tagName;
						})
					}
				}
			};
		}])
	});

	pApp.directive('pageableItem', function () {
		return {
			require: '^nqPageable',
			restrict: 'EAC',
			link: function postLink(scope, element, attr, controller) {

				var copt = controller.$options;
				element.removeClass(copt.selectionClass);
				if (copt.selectionMode == 'row' && copt.selectable) {
					element.on('click', function (evt) {
						if (!evt.isDefaultPrevented()) {
							element.toggleClass(copt.selectionClass);
							scope.$apply(function () {
								controller.setRowSelection(scope[controller.rowField])
							})
						}

					})
					scope.$watch(controller.rowField, function () {
						element.removeClass(copt.selectionClass);
					});
					scope.$on('$refreshPager', function () {
						element.removeClass(copt.selectionClass);
					})
				}
				scope.removeRow = function (item) {
					item = item || scope[controller.rowField];
					controller.removeRow(item);
				}
				scope.deleteRow = function (item) {
					item = item || scope[controller.rowField];
					controller.deleteRow(item);
				}
				if (scope.$last) {
					scope.$parent.$emit('$pageableItemsRendered')
				}
				scope.$isPageableItem = true;
			}
		};
	});
})(window, angular, undefined);

(function (window, angular) {
	'use strict';
	var defaults,
		editApp = angular.module('ngQuantum.pageable.editing', ['ngQuantum.services.templateHelper'])
			.provider('$pageableTemplate', function () {
				defaults = this.defaults = {
					name: 'pageableEditForm',
					templateId: 'pageableTemplate',
					onShow: false,
					onHide: false,
					onChange: false,
					disableRemote: true,
					alias: 'aliasModel',
					container: false,
					type: 'insertedit',
					insertPlacement: 'start',
					insertDefault: '{}',
					enterMethod: 'append',
					defaultTitle: 'Pageable Default Title',
					multipleMode: false,
					panelClasses: 'panel-default',
					templateUrl: 'pageable/editing.panel.tpl.html',
					noTemplate: false,
					effectClasses: 'fastest from-left'
				};
				this.$get = ['templateHelper', '$timeout', '$animate', '$compile', function (templateHelper, $timeout, $animate, $compile) {
					function Factory(element, config, controller) {

						var options = angular.extend({}, defaults, config),
							$parent = controller.$scope, tScope = $parent.$new();
						if (!controller.templates)
							controller.templates = {}
						else if (controller.templates[options.templateId])
							alert(options.templateId + ' already exist.');

						options.modelOptions = options.modelOptions ? $parent(options.modelOptions) : false;
						options.alias = config.alias || controller.rowField || 'pageableAlias';
						var type = options.type, html, transcluded = false, panel,
							container = options.container;
						controller.editOptions = options;

						if (container == 'self') {
							html = element[0].innerHTML;
							element.html(' ');
						} else {
							html = element[0].outerHTML;
							element.remove();
						}
						function templateTransclude(callback) {
							if (options.noTemplate) {
								normalizeTemplate(angular.element(html))
								callback && callback();
							}
							else
								templateHelper.fetchTemplate(options.templateUrl).then(function (template) {
									if (!angular.isElement(template))
										template = angular.element(template);
									var transclude = template.find('.pageable-template-transclude');
									transclude.length && transclude.html(html) || template.append(html);
									normalizeTemplate(template)
									callback && callback();
								});
						}
						function normalizeTemplate(template) {
							var normalized, typeClasses = 'pageable-template-' + type;

							if (/over|self/.test(container))
								typeClasses += ' pageable-template-' + container;
							if (options.multipleMode) {
								if (controller.elementTag == 'tr') {
									var colspan = getTableColumnCount(controller.tableElement[0]);
									normalized = '<tr class="' + typeClasses + '"><td colspan="' + colspan + '">' + template[0].outerHTML + '</td></tr>';
								} else {
									var tag = elementTag;
									normalized = '<' + tag + 'class="' + typeClasses + '">' + template[0].outerHTML + '</' + tag + '>';
								}
								container = options.container = 'over';
							} else {
								normalized = template.addClass(typeClasses)[0].outerHTML;
								if (!/over|self/.test(container)) {
									panel = angular.element(container);
									panel = panel.length ? panel.first() : controller.$container;
								}
								else if (container == 'self')
									panel = element;
								else
									panel = controller.$container;

							}

							if (type == 'insertedit') {
								tScope.insertTemplate = normalized;
								tScope.editTemplate = normalized;
							}
							else
								tScope[type + 'Template'] = normalized;
							console.log('type', type)
							transcluded = true;
						}
						function getTableColumnCount(table) {
							var columnCount = 0;
							var rows = table.rows;
							if (rows.length > 0) {
								var cells = rows[0].cells;
								for (var i = 0, len = cells.length; i < len; ++i) {
									columnCount += cells[i].colSpan;
								}
							}
							return columnCount;
						}
						var initialize = function (scope, tType) {
							var $child = scope.$new(), templateKey = tType + 'Template', viewKey = tType + 'View';
							$child.templateType = tType;
							$child.defaultTitle = options.defaultTitle;
							function _show() {
								if (options.multipleMode && scope[viewKey])
									return;
								else if (!options.multipleMode && container !== 'over' && tScope[viewKey]) {
									getRowField();
									return;
								}
								var viewEl = angular.element(tScope[templateKey]),
									parent,
									after;
								console.log('dsdsds', viewEl, tScope)
								if (container == 'over') {
									parent = controller.shellElement;
									var items = controller.shellElement.find('.pageable-item');
									if (tType == 'insert')
										after = options.insertPlacement != 'end' ? false : items.last();
									else
										after = scope.$isPageableItem && scope.$index > -1 ? items.eq(scope.$index) : false;
								}
								else {
									parent = panel;
									after = container == 'self' || options.enterMethod == 'append' ? false : panel.children().last();
								}
								$timeout(function () {
									viewEl.addClass('pageable-template-wrapper').addClass(options.effectClasses)

									if (options.multipleMode) {
										scope[viewKey] = viewEl;
										$animate.enter(viewEl, parent, after);
									} else {
										var promise = tScope[viewKey] ? $animate.leave(tScope[viewKey]) : { then: function (c) { c(); } };
										promise.then(function () {
											$animate.enter(viewEl, parent, after);
											tScope[viewKey] = viewEl;
										})
									}
									$compile(viewEl)($child);
									$child.viewEl = viewEl;
									options.onShow && scope.$eval(options.onShow);
									scope.$panelClasses = options.panelClasses
								}, 0);
							};
							function getRowField() {
								$timeout(function () {
									var extend = tType == 'insert' ? scope.$eval(options.insertDefault) : scope[controller.rowField];
									$child[options.alias] = {};
									$child[options.alias] = angular.copy(extend, {});
									options.onChange && scope.$eval(options.onChange);
								})
							}
							scope.$on('$refreshPager', function () {
								$child.$back();
							})
							$child.$back = function () {
								var viewObj = options.multipleMode ? scope : tScope;
								var viewEl = viewObj[viewKey];
								viewEl && viewEl.length && $animate.leave(viewEl).then(function () { viewEl.remove() });
								viewObj[viewKey] = false;
								options.onHide && scope.$eval(options.onHide);
							};
							$child.$show = function () {
								getRowField();
								if (transcluded)
									_show();
								else
									templateTransclude(_show);
							};
							if (tType !== 'detail') {
								function setRowField() {
									$timeout(function () {
										if (tType !== 'insert')
											scope[controller.rowField] = angular.copy($child[options.alias], {});
										options.onChange && scope.$eval(options.onChange);
									})

								}
								function save() {
									var formCtrl = $child[options.name];
									if (options.modelOptions && options.modelOptions.updateOn == 'submit') {
										formCtrl && formCtrl.$commitViewValue();
									}
									formCtrl.$commitViewValue();
									formCtrl.$setSubmitted();
									formCtrl.$$parentForm.$setValidity();
									if (formCtrl.$invalid)
										return;
									if (options.disableRemote) {
										tType == 'edit' ? setRowField() : controller.addRow($child[options.alias]);
										$child.$back();
									} else {
										var promise = controller.saveRow($child[options.alias], tType == 'insert');
										promise.then(function () {
											$child.$back();
										})
									}

								}

								$child.$cancel = function () {
									getRowField();
								};
								$child.$save = function () {
									$timeout(function () {
										save();
									}, 0)
								};
								$child.$delete = function () {
									$timeout(function () {
										controller.deleteRow(scope[controller.rowField]);
										$child.$back();
									}, 0)
								};
								$child.$submit = function (evt) {
									var form = $child.viewEl.find('.pageable-template-container');
									$timeout(function () {
										form.triggerHandler('submit')
									}, 0)

								};
							}

							return $child;
						}
						var $factory = {
							initialize: initialize
						}
						controller.templates[options.templateId] = $factory;
						return $factory;
					}
					return Factory;
				}
				];
			})
			.directive('nqPageableTemplate', ['$pageableTemplate', function ($pageableTemplate) {
				return {
					restrict: 'A',
					require: '^nqPageable',
					terminal: true,
					scope: false,
					priority: 1000,
					compile: function (tElm, tAttrs, transclude) {
						tElm.removeAttr('nq-pageable-template');
						tElm.removeAttr('data-nq-pageable-template');
						!tAttrs.type && tAttrs.$set('type', 'insertedit');
						!/edit|insert|detail|insertedit/.test(tAttrs.type) && tAttrs.$set('type', 'insertedit');
						if (tAttrs.type !== 'detail')
							!tAttrs.name && tAttrs.$set('name', 'pageableEditForm');
						return function postLink(scope, element, attr, controller) {
							var options = {}
							for (var o in defaults) {
								if (angular.isDefined(attr[o])) {
									options[o] = attr[o];
								}
							}
							element.addClass('pageable-template-container')
							angular.isDefined(attr.ngModelOptions) && (options.modelOptions = attr.ngModelOptions)
							var template = new $pageableTemplate(element, options, controller)
						}
					}
				};
			}]);
	angular.forEach(['Edit', 'Insert', 'Detail'], function (directive, index) {
		editApp.directive('nqShow' + directive, function () {
			return {
				restrict: 'A',
				require: '^nqPageable',
				link: function postLink(scope, element, attr, controller) {
					var initialized = false, $child;
					element.on('click', handler);
					function init() {
						if (!controller.templates) {
							off(); return;
						}
						var templateId = attr.templateId, template;
						if (templateId && controller.templates.hasOwnProperty(templateId))
							template = controller.templates[templateId]
						else
							template = controller.templates[Object.keys(controller.templates)[0]];
						if (!angular.isObject(template) || !template.hasOwnProperty('initialize')) {
							off(); return;
						}
						$child = template.initialize(scope, directive.toLowerCase());
					}
					function handler(evt) {
						evt.preventDefault();
						!initialized && init();
						$child && $child.$show();
					}
					function off() {
						element.off('click', handler);
					}
				}
			};
		})
	})

})(window, window.angular)
'use strict';
angular.module('ngQuantum.pageable.editing')
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('pageable/editing.panel.tpl.html',
			'<div class="panel pageable-edit-panel panel-stretch" ng-class="$panelClasses">'
			+ '<div class="panel-heading">'
			+ '<h2 class="panel-title" ng-bind-html="panelTitle || defaultTitle"></h2>'
			+ '</div>'
			+ '<div class="panel-body pageable-template-transclude">'
			+ '</div>'
			+ '<div class="panel-footer clearfix">'
			+ '<div class="pull-left">'
			+ '<button class="btn btn-danger" type="button" ng-click="$back()">Back</button>'
			+ '<button class="btn btn-warning" type="button" ng-click="$cancel()"  ng-if="templateType != \'detail\'">Cancel</button>'
			+ '</div>'
			+ '<div class="pull-right" ng-if="templateType != \'detail\'">'
			+ '<button class="btn btn-primary" type="button" ng-click="$submit($event)">Save</button>'
			+ '</div>'
			+ '</div>'
			+ '</div>'
		);
	}])

'use strict';
angular.module('ngQuantum.pageable.factory', ['ngQuantum.services.helpers'])
	.provider('$pageable', function () {
		var defaults = this.defaults = {
			effect: 'fade-in',
			speed: 'fastest',
			theme: false,
			placement: 'bottom',
			pageNumbers: 3,
			pageSize: 10,
			showSize: true,
			showResultText: true,
			sizeOptions: [10, 20, 30, 40, 50],
			startPage: 1,
			firstLast: true,
			prevNext: true,
			firstText: 'First',
			lastText: 'Last',
			nextText: 'Next',
			previousText: 'Previous',
			currentPageText: 'Current Page',
			totalPageText: 'Total Pages',
			totalResultText: 'Total Results',
			noTotalResultText: 'Your server response do not have "totalResult" field. Pager cannot be displayed.',
			sizesText: 'Size :',
			remotePaging: false,
			dataType: 'json',
			method: 'GET',
			methodFilter: 'POST',
			methodDelete: 'DELETE',
			methodUpdate: 'PUT',
			paramsField: 'PageableRequest',
			primaryKeys: false,
			serverRoot: false,
			baseUrl: false,
			deleteSuffix: false,
			updateSuffix: false,
			insertSuffix: false,
			routeParams: false,
			useQueryString: false,
			refreshOnChange: true,
			cacheResult: false,
			templateUrl: false,
			pagerTamplate: false,
			lazyAjax: true,
			selectable: false,
			selectionMode: 'row',
			selectionClass: 'active',
			recordsField: 'records',
			totalField: 'totalResult'
		};
		this.$get = ['$timeout', '$filter', '$http', '$rootScope', '$parse', '$helpers', '$q', '$lazyRequest',
			function ($timeout, $filter, $http, $rootScope, $parse, $helpers, $q, $lazyRequest) {
				function Factory(element, config, attr) {

					var $pageable = {}, options = {}, currentPage = 1;
					attr && (config = $helpers.parseOptions(attr, config))

					options = $pageable.$options = angular.extend(defaults, config);
					var scope = $pageable.$scope = options.$scope || $rootScope.$new();
					if (attr) {
						if (angular.isDefined(attr.qoAllOptions)) {
							options = scope.$eval(attr.qoAllOptions)
						} else {
							options = $pageable.$options = $helpers.observeOptions(attr, $pageable.$options);
							angular.forEach(['formatRequest', 'formatData', 'loadError', 'deleted', 'updated', 'inserted', 'onRefresh'],
								function (val) {
									if (angular.isDefined(attr[val])) {
										options[val] = $parse(attr[val]);
									}
								})
						}

					}

					scope.$pageableBusy = true;
					scope.$modelKey = options.pageableModel;
					var modelData = [], sortedData;
					$pageable.caches = {};
					$pageable.init = function () {
						var promise;
						optimize();
						if (options.baseUrl) {
							if (options.lazyAjax) {
								promise = $lazyRequest(function () {
									return $pageable.loadRemote();
								}, 0)
							}
							else
								promise = $pageable.loadRemote();
						}
						if (!promise)
							promise = $q.when(null);
						promise.then(function () {
							scope.selectedRows = [];
							scope.$pageableBusy = false;
						})
					};
					$pageable.setModelData = function (data, isServer, error) {
						var promise;
						if (error) {
							promise = $timeout(function () {
								scope.$error = true;
								scope.$currentRows = [];
								modelData = scope[scope.$modelKey] = [];
								scope.$currentPage = 0;
								scope.totalResult = 0;
							}, 0)
						}
						else {
							if (angular.isArray(data)) {
								if (options.remotePaging) {
									promise = $timeout(function () {
										scope.$pagerWarning = options.noTotalResultText;
										scope.$currentPage = 0;
										scope.totalResult = 0;
										$pageable.getRows(data);
									}, 0)
								}
								else {
									promise = $timeout(function () {
										scope.$pagerWarning = false;
										modelData = scope[scope.$modelKey] = data || [];
										scope.totalResult = modelData.length;
										$pageable.getRows();
									}, 0)

								}
							} else if (angular.isObject(data)) {
								var total, array;
								total = $helpers.getFieldValue(data, options.totalField);
								array = $helpers.getFieldValue(data, options.recordsField);

								if (!total || !array) {
									for (var o in data) {
										if (!total && angular.isNumber(data[o]))
											total = data[o];
										if (!array && angular.isArray(data[o]))
											array = data[o]
										if (array && total)
											break;
									}
								}
								promise = $timeout(function () {
									scope.totalResult = total;
									if (options.remotePaging) {
										scope.totalResult = total;
										modelData = array;
										$pageable.getRows(array, total);

									} else {
										modelData = scope[scope.$modelKey] = array || [];
										$pageable.getRows();
									}
								}, 0)

							}
							if (promise && promise.then)
								promise.then(function () {
									$pageable.localdata = modelData.slice();
								})

						}
					}
					$pageable.getRows = function (newrows, total) {
						var rows = newrows || [];
						var cp = scope.$currentPage = scope.$currentPage || options.startPage || 1;
						scope.$pageSize = scope.$pageSize || options.pageSize || 10;
						if (!rows.length) {
							if (options.remotePaging) {
								if (!newrows)
									$pageable.loadRemote();
								else if (!newrows.length)
									setRows();
							}
							else {

								var start = (cp - 1) * scope.$pageSize;
								rows = modelData.slice(start, start + scope.$pageSize);
								setRows()
							}
						}
						else {
							setRows();
						}
						function setRows() {
							$timeout(function () {
								!total && (scope.totalResult = modelData.length);
								scope.$currentRows = rows;
								setTotalPages();
								scope.$broadcast('$refreshPager')
							}, 0);
						}

					}
					$pageable.gotoPage = function (val) {
						$timeout(function () {
							!scope.$totalPages && setTotalPages();
							if (scope.$currentPage !== val && val > 0 && val <= scope.$totalPages) {
								scope.$currentPage = val;
								$pageable.getRows();
							}

						}, 0)
					}
					$pageable.loadRemote = function () {
						scope.$pageableBusy = true;
						var obj = { params: loadingParams(), url: buildUrl(), eventType: 'load' }, ajax = {};

						if (options.formatRequest) {
							ajax = callFormatUrl(obj)
						}
						else {

							var post = options.method.toLowerCase() == 'post';
							ajax.method = post ? 'POST' : 'GET';
							var prm = angular.extend({}, obj.params.routeParams);
							if (post) {
								ajax.url = buildUrl(prm);
								var data = angular.extend({}, obj.params)
								data.routeParams && delete data.routeParams;
								ajax.data = {}, ajax.data[options.paramsField] = data;
							}
							else {
								prm = angular.extend({}, prm, obj.params.pageParams, obj.params.sortParams, { 'searchTerm': obj.params.searchTerm });
								ajax.url = buildUrl(prm);
							}
							if (options.useQueryString) {
								ajax.params = prm;
							}
						}
						ajax && (ajax.cache = options.cacheResult);

						if (ajax)
							return $http(ajax)
								.success(function (res) {
									var data = res.data ? res.data : res;
									if (options.formatData) {
										data = options.formatData(scope, { $response: res })
									}
									scope.$noResultFound = !data.length;
									$pageable.setModelData(data, true);
									scope.$pageableBusy = false;
									scope.$errorResponse = '';
									scope.$error = false;
								})
								.error(function (res) {
									scope.$pageableBusy = false;
									scope.$noResultFound = true;
									if (options.loadError) {
										var data = options.loadError(scope, { $response: res })
									}
									scope.$errorResponse = res;
									$pageable.setModelData(null, true, true)
								});
					}


					$pageable.sortTable = function (field, direction) {
						var multiple = options.sortingMode == 'multiple';
						if (options.remotePaging) {
							setSortKey(field, direction, multiple);
							scope.$currentPage = 1;
							$pageable.loadRemote();
						}
						else {
							if (multiple) {
								if (!sortedData)
									sortedData = angular.extend({}, $pageable.localdata)
								modelData = $filter('orderBy')(sortedData, field, direction == 'desc' ? true : false);
							}
							else
								modelData = $filter('orderBy')($pageable.localdata, field, direction == 'desc' ? true : false);
							$pageable.getRows();
						}

					}
					$pageable.searchTable = function (fields, term) {
						scope.$currentPage = 1;
						if (options.remotePaging) {
							scope.searchTerm = term;
							$pageable.loadRemote();
						}
						else {
							modelData = $filter('filter')($pageable.localdata, function (item, key) {
								var match = false, i = 0;
								while (!match && i < fields.length) {
									var value = $helpers.getFieldValue(item, fields[i]);
									if (value) {
										if (angular.isString(value))
											match = (value.toLowerCase()).indexOf(term.toLowerCase()) > -1;
										else
											match = (value == term);
									}

									i++;
								}
								return match;
							});
							scope.totalResult = modelData.length;
							$pageable.getRows();
						}

					}
					$pageable.refresh = function (full) {
						scope.$currentPage = 1;
						sortedData = false;
						if (options.remotePaging || (full && options.baseUrl)) {
							scope.searchTerm = false;
							scope.sortParam = false;
							scope.totalResult = 0;
							$pageable.loadRemote();
						}
						else {
							$timeout(function () {
								modelData = $pageable.localdata.slice();
								scope.totalResult = modelData.length;
								$pageable.getRows();
							}, 0)

						}
						scope.selectedRows = [];
					}



					scope.$watch('$pageSize', function (newVal, oldVal) {
						if (newVal && oldVal && oldVal !== newVal) {
							scope.selectedRows = [];
							$pageable.getRows();
						}
					})
					function optimize() {
						if (angular.isString(options.sizeOptions))
							options.sizeOptions = eval(options.sizeOptions);
					}
					function callFormatUrl(obj) {
						if (options.formatRequest) {
							var called = options.formatRequest(scope, { $url: obj.url, $params: obj.params, $eventType: obj.eventType });
							if (angular.isString(called)) {
								obj.url = called;
								obj.params = false;
							} else if (angular.isObject(called)) {
								url = called.url;
								obj.params = called.params;
							}
						}
						return obj;
					}
					function loadingParams() {
						var params = {};
						var rp = routeParams();
						if (rp) params.routeParams = rp;
						params.pageParams = pageParams();
						if (scope.sortParam) params.sortParams = scope.sortParam;
						if (scope.searchTerm) params.searchTerm = scope.searchTerm;
						return params == {} ? undefined : params;
					}
					function deletingParams(items) {
						var params = {};
						var rp = routeParams();
						rp && (params.routeParams = rp);
						params.items = deleteParams(items);
						return params;
					}
					function routeParams() {
						var params = {};
						if (options.routeParams) {
							if (angular.isArray(options.routeParams)) {
								var arr = options.routeParams;
								for (var i = 0; i < arr.length; i++) {
									if ($rootScope.params[arr[i]])
										params[arr[i]] = $rootScope.params[arr[i]];
								}
							} else if (angular.isString(options.routeParams))
								if ($rootScope.params[options.routeParams])
									params[options.routeParams] = $rootScope.params[options.routeParams];
						}
						return params == {} ? false : params;
					}
					function pageParams() {
						return {
							pageno: scope.$currentPage || options.startPage || 1,
							pagesize: scope.$pageSize || options.pageSize || 10
						};
					}
					function deleteParams(items) {
						if (items) {
							if (angular.isArray(items) && items.length) {
								var params = [];
								angular.forEach(items, function (item) {
									var prm = getPrimaryParams(item);
									prm && params.push(prm);
								})
								return params.length ? params : false;
							}
							else if (angular.isObject(items))
								return getPrimaryParams(items)
						}
						return false;
					}
					function getPrimaryParams(item) {
						var keys = options.primaryKeys && options.primaryKeys.split(',') || [], params = {};
						angular.forEach(keys, function (val) {
							params[val] = item[val];

						})
						return params == {} ? false : params
					}
					function setSortKey(key, type, multiple) {
						var prm = {
							sortKey: key,
							direction: type
						}
						if (multiple) {
							scope.sortParam = angular.extend(scope.sortParam, prm);
						}
						else
							scope.sortParam = prm;

					}

					function buildUrl(params, suffix) {
						var url = (options.serverRoot || '') + options.baseUrl;
						if (suffix)
							url = url.trimEnd('/'), url = url + suffix;
						if (!options.useQueryString && params) {
							url = $helpers.formatUrl(url, params)
						}
						return url;
					}

					function setTotalPages() {
						scope.allPages = [];
						var length = scope.totalResult;
						scope.$totalPages = 1;
						if (length % (scope.$pageSize || 10) == 0)
							scope.$totalPages = (length / (scope.$pageSize || 10))
						else
							scope.$totalPages = parseInt(length / (scope.$pageSize || 10) + 1);
						if (scope.$totalPages)
							for (var i = 1; i <= scope.$totalPages; i++) {
								scope.allPages.push(i);
							}

					}
					function splicePages(pageNumbers, pages) {
						var newPages = pages && pages.slice() || [], allPages = scope.allPages;
						if (scope.$currentPage < pageNumbers || scope.$totalPages == pageNumbers)
							newPages = allPages.slice(0, spliceValue(pageNumbers))
						else if (pages.length) {
							if (pages.length < pageNumbers || scope.$totalPages == scope.$currentPage) {
								var start = scope.$totalPages - pageNumbers > 0 ? scope.$totalPages - pageNumbers : 0;
								newPages = allPages.slice(start, spliceValue(scope.$totalPages))
							}
							else if (scope.$currentPage == pages[pages.length - 1])
								newPages = allPages.slice(scope.$currentPage - 1, spliceValue(pageNumbers + scope.$currentPage - 1));
							else if (scope.$currentPage == pages[0])
								newPages = allPages.slice(scope.$currentPage - pageNumbers, spliceValue(scope.$currentPage))

						}
						else {
							var start = scope.$currentPage - pageNumbers > 0 ? scope.$currentPage - pageNumbers : 0;
							newPages = allPages.slice(start, spliceValue(pageNumbers + scope.$currentPage - 1))
						}

						return newPages;
					}
					function spliceValue(number) {
						return number < scope.$totalPages ? number : scope.$totalPages
					}
					function deleteRow(item) {
						var items = item || scope.selectedRows, dparams = deletingParams(items);
						if (!items || !dparams.items)
							return false;
						scope.$deletingProcess = true;
						var obj = { params: dparams, url: buildUrl(null, options.deleteSuffix), eventType: 'delete' }, ajax = {};
						if (options.formatRequest) {
							ajax = callFormatUrl(obj)
						}
						else {
							var prm = angular.extend({}, obj.params.routeParams)
							if (angular.isArray(items) || options.methodDelete.toLowerCase() == 'post') {
								ajax.url = buildUrl(prm, options.deleteSuffix);
								ajax.method = 'POST';
								ajax.data[options.paramsField] = obj.items;

							}
							else {
								prm = angular.extend({}, obj.params.routeParams, obj.params.items)
								ajax.url = buildUrl(prm, options.deleteSuffix);
								ajax.method = options.methodDelete;
							}

							if (options.useQueryString) {
								ajax.params = prm;
							}
						}
						if (ajax)
							return $http(ajax)
								.success(function (res) {
									var data = res.data ? res.data : res;
									if (data != false)
										removeRows(items);
									scope.$deletingProcess = false;
									options.deleted && options.deleted(scope, { $response: res });
									if (options.refreshOnChange)
										$pageable.getRows();
								})
								.error(function (res) {
									scope.$deletingProcess = false;
									options.deleted && options.deleted(scope, { $response: res, $error: true })
								});
					}
					function removeRows(items) {
						angular.forEach(items, function (item) {
							removeRow(item);
						})
					}
					function removeRow(item) {
						var index = -1;
						if ($pageable.localdata && $pageable.localdata.length && (index = $pageable.localdata.indexOf(item)) > -1)
							$pageable.localdata.splice(index, 1);
						if (sortedData && sortedData.length && (index = sortedData.indexOf(item)) > -1)
							sortedData.splice(index, 1);
						if (modelData && modelData.length && (index = modelData.indexOf(item)) > -1)
							modelData.splice(index, 1);
						if (scope.$currentRows.length && (index = scope.$currentRows.indexOf(item)) > -1)
							scope.$currentRows.splice(index, 1);

						setRowSelection(item);
						return true;
					}
					function saveRow(item, isNew) {
						;
						if (!item)
							return false;
						scope.$savingProcess = true;
						var rp = routeParams(),
							eventType = isNew ? 'insert' : 'update',
							method = isNew ? 'POST' : options.methodUpdate,
							parseKey = isNew ? 'inserted' : 'updated',
							obj = { params: { routeParams: rp, data: item }, url: buildUrl(null, options[eventType + 'Suffix']), eventType: eventType }, ajax = {};
						if (options.formatRequest) {
							ajax = callFormatUrl(obj)
						}
						else {
							ajax.url = buildUrl(rp, options[eventType + 'Suffix']);
							ajax.method = method;
							ajax.data[options.paramsField] = item;

							if (options.useQueryString && rp) {
								ajax.params = rp;
							}
						}
						if (ajax)
							return $http(ajax)
								.success(function (res) {
									var data = res.data ? res.data : res;
									if (isNew && data) {
										angular.extend(item, data);
										addRow(item)
									}
									scope.$savingProcess = false;
									options[parseKey] && options[parseKey](scope, { $response: res });
									if (options.refreshOnChange)
										$pageable.getRows();
								})
								.error(function (res) {
									scope.$savingProcess = false;
									options[parseKey] && options[parseKey](scope, { $response: res, $error: true })
								});

						return $q.when('');
					}
					function addRow(item) {
						if (!item)
							return false;
						scope.$currentRows.unshift(item);
						modelData.unshift(item);
						$pageable.localdata.unshift(item)
						$timeout(function () {
							scope.totalResult++;
							setTotalPages();
							scope.$broadcast('$refreshPager')
						}, 0);

						return true;
					}
					function setRowSelection(item) {
						var index = scope.selectedRows.indexOf(item);
						if (index < 0)
							scope.selectedRows.push(item);
						else
							scope.selectedRows.splice(index, 1);
					}
					$pageable.splicePages = function (pageNumbers, pages) {
						return splicePages(pageNumbers, pages);
					}
					$pageable.setRowSelection = setRowSelection;
					$pageable.removeRow = function (item) {
						removeRow(item)
						if (options.refreshOnChange)
							$pageable.getRows();
						else {
							$timeout(function () {
								scope.totalResult--;
								setTotalPages();
							}, 0)

						}
					};
					$pageable.removeRows = function (items) {
						items = items || scope.selectedRows;
						angular.forEach(items, function (item) {
							$pageable.removeRow(item);
						})
					};
					$pageable.deleteRow = deleteRow;
					$pageable.addRow = addRow;
					$pageable.saveRow = saveRow;
					scope.$$postDigest(function () {
						scope.$first = function () {
							$pageable.gotoPage(1);
						}
						scope.$last = function () {
							$pageable.gotoPage(scope.$totalPages);
						}
						scope.$prev = function () {
							$pageable.gotoPage(scope.$currentPage - 1);
						}
						scope.$next = function () {
							$pageable.gotoPage(scope.$currentPage + 1);
						}
						scope.$gotoPage = function (val) {
							$pageable.gotoPage(val);
						}

					});
					if (options.onRefresh) {
						scope.$on('$refreshPager', function () {
							options.onRefresh(scope)
						})
					}
					$pageable.init();
					return $pageable;
				}
				return Factory;
			}
		];
	});
'use strict';
angular.module('ngQuantum.pageable.pager', [])
	.directive('nqPager', ['$timeout', function ($timeout) {
		return {
			require: '^nqPageable',
			restrict: 'EA',
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return 'pageable/pager.tpl.html'
			},
			scope: true,
			link: function postLink(scope, element, attr, controller) {
				var locale = scope.$locale = scope.$locale || {}, copt = controller.$options;
				angular.forEach(['previousText', 'nextText'],
					function (key) {
						if (angular.isDefined(attr[key])) {
							scope.$locale[key] = attr[key];
						}
						else if (angular.isDefined(copt[key])) {
							scope.$locale[key] = copt[key];
						}
					});
				var theme = attr.theme || copt.theme;
				if (theme) {
					element.addClass('pager-' + theme)
				}
				var size = attr.sizeClass || copt.sizeClass;
				if (size) {
					element.addClass('pager-' + size)
				}
				scope.$aligned = attr.aligned;
				scope.$on('$refreshPager', function () {
					$timeout(function () {
						scope.$pagerWarning = controller.$scope.$pagerWarning;
						scope.$currentPage = controller.$scope.$currentPage;
						scope.$pageSize = controller.$scope.$pageSize;
						scope.$totalResult = controller.$scope.$totalResult;
						scope.$totalPages = controller.$scope.$totalPages;
					}, 0);
				});
				scope.$$postDigest(function () {
					scope.$prev = controller.$scope.$prev;
					scope.$next = controller.$scope.$next;
					scope.$gotoPage = controller.$scope.$gotoPage;
				});

			}
		};
	}])
'use strict';
angular.module('ngQuantum.pageable.pager')
	.run(['$templateCache', function ($templateCache) {
		$templateCache.put('pageable/pager.tpl.html',
			'<ul class="pager">'
			+ '<li ng-class="{disabled:$currentPage < 2, previous:$aligned}" class="page-button previous"><a role="button" tabindex="0" ng-click="$prev()"><i class="fic fu-angle-l"></i> {{$locale.previousText}}</a></li>'
			+ '<li ng-class="{disabled:$totalPages == $currentPage, previous:$aligned}" class="page-button next"><a role="button" tabindex="0" ng-click="$next()">{{$locale.nextText}} <i class="fic fu-angle-r"></i> </a></li>'
			+ '</ul>'
			+ '<div ng-show="$pagerWarning"><span class="label label-warning"></span><span ng-bind="$pagerWarning"></span></div>'
		);
	}])


'use strict';
angular.module('ngQuantum.pageable.pagesize', ['ngQuantum.services.templateHelper', 'ngQuantum.services.helpers'])
	.directive('nqPagingSizes', ['$helpers', '$parse', function ($helpers, $parse) {
		return {
			restrict: 'A',
			require: '^nqPageable',
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return attr.nqPagingSizes == 'buttons' ? 'pageable/pagesize.buttongroup.tpl.html' : 'pageable/pagesize.select.tpl.html';
			},
			link: function postLink(scope, element, attr, controller) {
				var type = attr.nqPagingSizes || 'select';

				var sizeOptions = angular.isDefined(attr.sizeOptions) ? $helpers.parseConstant(attr.sizeOptions) : controller.$options.sizeOptions;
				if (!angular.isArray(sizeOptions))
					sizeOptions = controller.$options.sizeOptions;
				scope.sizeOptions = sizeOptions;
				if (type !== 'buttons')
					scope.$selectClasses = 'btn-sm btn-default';
				else {
					scope.$buttonClasses = 'btn-default';
					scope.$buttonGroupClasses = 'btn-group-sm'
				}
				scope.$locale = scope.$locale || {};
				scope.$locale.sizesText = ($helpers.parseConstant(attr.sizesText) !== false) && (attr.sizesText || controller.$options.sizesText || false);
				angular.forEach(['selectClasses', 'buttonGroupClasses', 'buttonClasses'], function (val, key) {
					if (angular.isDefined(attr[val]))
						attr.$observe(val, function (newVal) {
							newVal && (scope['$' + val] = newVal)
						})
				})
				var onSizeChange = attr.onSizeChange ? $parse(attr.onSizeChange) : false;
				if (onSizeChange)
					scope.$watch('$pageSize', function (newVal) {
						onSizeChange(scope, { $pageSize: newVal })
					})
			}
		};
	}])
'use strict';
angular.module('ngQuantum.pageable.pagesize')
	.run(['$templateCache', function ($templateCache) {
		$templateCache.put('pageable/pagesize.select.tpl.html',
			'<div class="page-size-container">'
			+ '<small class="size-text" ng-bind="$locale.sizesText"></small>'
			+ '<button type="button" ng-model="$pageSize" nq-select="" ng-change="$parent.$pageSize = $pageSize" data-qo-filterable="false" data-qo-html="false" ng-options="item for item in sizeOptions"'
			+ ' data-ng-bind="$locale.sizesText" data-qo-placeholder="size..." data-qo-disable-clear="true" class="btn page-size-select" ng-class="$selectClasses">'
			+ '</button>'
			+ '<div>'
		);
		$templateCache.put('pageable/pagesize.buttongroup.tpl.html',
			'<div class="page-size-container">'
			+ '<small class="size-text" ng-bind="$locale.sizesText"></small>'
			+ '<div ng-model="$parent.$pageSize" nq-radio-group=""  class="btn-group btn-group-page-size" ng-class="$buttonGroupClasses">'
			+ '<label ng-repeat="item in sizeOptions" class="btn"  ng-class="$buttonClasses"><input name="pageSizeValue" type="radio" ng-value="item"/><span ng-bind="item"></span></label>'
			+ '</div>'
			+ '<div>'
		);
	}])
'use strict';
angular.module('ngQuantum.pageable.pagination', [])
	.directive('nqPagination', ['$timeout', function ($timeout) {
		return {
			require: '^nqPageable',
			restrict: 'EA',
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return 'pageable/pagination.tpl.html'
			},
			scope: true,
			link: function postLink(scope, element, attr, controller) {
				var locale = scope.$locale = scope.$locale || {}, copt = controller.$options;
				scope.pages = [];
				angular.forEach(['firstText', 'lastText', 'previousText', 'nextText'],
					function (key) {
						if (angular.isDefined(attr[key])) {
							scope.$locale[key] = attr[key];
						}
						else if (angular.isDefined(copt[key])) {
							scope.$locale[key] = copt[key];
						}
					});
				angular.forEach(['firstLast', 'prevNext', 'cssClass'],
					function (key) {
						if (angular.isDefined(attr[key])) {
							scope['$' + key] = attr[key];
						}
						else if (angular.isDefined(copt[key])) {
							scope['$' + key] = copt[key];
						}
					});

				var pageNumbers = attr.pageNumbers || copt.pageNumbers || 3;
				var theme = attr.theme || copt.theme;
				if (theme) {
					element.addClass('pagination-' + theme)
				}
				var size = attr.sizeClass || copt.sizeClass;
				if (size) {
					element.addClass('pagination-' + size)
				}
				scope.$on('$refreshPager', function () {
					$timeout(function () {
						scope.$pagerWarning = controller.$scope.$pagerWarning;
						scope.$currentPage = controller.$scope.$currentPage;
						scope.$totalResult = controller.$scope.$totalResult;
						scope.$pageSize = controller.$scope.$pageSize;
						var newPages = controller.splicePages(pageNumbers, scope.pages);
						scope.pages = newPages;
						scope.$totalPages = controller.$scope.$totalPages;
					}, 0);
				});
				scope.$$postDigest(function () {
					scope.$first = controller.$scope.$first
					scope.$last = controller.$scope.$last
					scope.$prev = controller.$scope.$prev
					scope.$next = controller.$scope.$next
					scope.$gotoPage = controller.$scope.$gotoPage
				});

			}
		};
	}])
'use strict';
angular.module('ngQuantum.pageable.pagination')
	.run(['$templateCache', function ($templateCache) {
		$templateCache.put('pageable/pagination.tpl.html',
			'<ul class="pagination" ng-class="$cssClass" ng-show="$totalPages > 1">'
			+ '<li ng-if="$firstLast" ng-class="{disabled:$currentPage < 2}" class="page-button first"><a role="button" tabindex="0" ng-click="$first()" class="titip-top" data-title="{{$locale.firstText}}"><i class="fic fu-arrow-left"></i></a></li>'
			+ '<li ng-if="$prevNext" ng-class="{disabled:$currentPage < 2}" class="page-button previous"><a role="button" tabindex="0" ng-click="$prev()" class="titip-top" data-title="{{$locale.previousText}}"><i class="fic fu-angle-l"></i></a></li>'
			+ '<li class="page-number" ng-class="{active:page == $currentPage, lastActive: $totalPages == $currentPage}" ng-repeat="page in pages"><a role="button" tabindex="0" ng-click="$gotoPage(page)">{{page}}</a></li>'
			+ '<li ng-if="$prevNext"  ng-class="{disabled:$totalPages == $currentPage}" class="page-button next"><a role="button" tabindex="0" ng-click="$next()"  class="titip-top" data-title="{{$locale.nextText}}"><i class="fic fu-angle-r"></i></a></li>'
			+ '<li ng-if="$firstLast" ng-class="{disabled:$totalPages == $currentPage}" class="page-button last"><a role="button" tabindex="0" class="titip-top" data-title="{{$locale.lastText}}" ng-click="$last()"><i class="fic fu-arrow-right"></i></a></li>'
			+ '</ul>'
			+ '<div ng-show="$pagerWarning"><span class="label label-warning"></span><span ng-bind="$pagerWarning"></span></div>'
		);
	}])

'use strict';
angular.module('ngQuantum.pageable.results', [])
	.directive('nqPageableResults', function () {
		return {
			restrict: 'A',
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return 'pageable/pageableResults.tpl.html'
			},
			require: '^nqPageable',
			link: function (scope, elm, attr, controller) {
				var copt = controller.$options; scope.$locale = scope.$locale || {};
				var theme = attr.theme || copt.theme;
				if (theme)
					elm.addClass('pageable-results-' + theme);
				angular.forEach(['currentPageText', 'totalResultText', 'totalPageText'],
					function (key) {
						if (angular.isDefined(attr[key])) {
							scope.$locale[key] = attr[key];
						}
						else if (angular.isDefined(copt[key])) {
							scope.$locale[key] = copt[key];
						}
					});

			}
		};
	})
'use strict';
angular.module('ngQuantum.pageable.results')
	.run(['$templateCache', function ($templateCache) {
		$templateCache.put('pageable/pageableResults.tpl.html',
			'<div class="pageable-results">'
			+ '<p>'
			+ '<small ng-bind="$locale.currentPageText"></small> : <strong class="current-page" ng-bind="$currentPage"></strong>'
			+ '<small ng-bind="$locale.totalPageText"></small> :  <strong class="total-page" ng-bind="$totalPages"></strong>'
			+ '</p>'
			+ '<small ng-bind="$locale.totalResultText"></small> :  <strong class="total-result" ng-bind="totalResult"></strong>'
			+ '</div>'
		);
	}])
'use strict';
angular.module('ngQuantum.pageable.scroll', ['ngQuantum.scrollbar'])
	.directive('nqFixTableScroll', ['$compile', function ($compile) {
		return {
			restrict: 'C',
			require: '^nqPageable',
			priority: 0,
			compile: function (tElm, tAttrs, transclude) {
				var tag = tElm[0].tagName.toLowerCase();
				if (!/thead|tfoot/.test(tag))
					return;
				var tfoot = tag == 'tfoot';
				var parent = tElm.parent(), container = parent.parent(), appended = false;
				tElm.removeClass('nq-fix-table-scroll')
				var table = angular.element('<table style="position:absolute;"></table>').html(tElm.clone());
				tfoot && table.css('bottom', '0') || table.css('top', '0')
				return function postLink(scope, element, attr, controller) {
					var pos = container.css('position');
					(!pos || pos === 'static') && container.css('position', 'relative')
					container.on('scroll', function () {
						var scrollTop = container[0].scrollTop;
						if (scrollTop > 0) {
							append();
							show();
							if (tfoot) {
								table.css('bottom', -scrollTop);
								if (container[0].scrollHeight < (scrollTop + container[0].clientHeight + 10))
									table.hide();
							}
							else
								table.css('top', scrollTop);
						}
						else {
							table.hide();
							if (tfoot && parent.height() > container.height()) {
								show();
								table.css('bottom', 0);
							}
						}

					});
					scope.$on('$pageableItemsRendered', initFooter);
					function initFooter() {
						if (tfoot && parent.height() > container.height()) {
							append();
							show();
						}
					}
					function show() {
						table.show();
						table.css('width', parent.outerWidth())
					}
					function append() {
						if (!appended) {
							appended = true;
							table.attr('class', parent.attr('class'));
							parent.after(table);
							$compile(table)(scope);
							tfoot ? table.addClass('table-footer-clone') : table.addClass('table-header-clone');
						}
					}

				}
			}
		};
	}]);
'use strict';
angular.module('ngQuantum.pageable.search', [])
	.directive('nqTableSearch', [function () {
		return {
			restrict: 'A',
			require: '^nqPageable',
			scope: true,
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return 'pageable/tablesearch.tpl.html'
			},
			link: function (scope, element, attr, controller) {
				element.addClass('page-searching');
				scope.$inputGroupClasses = 'input-group-sm input-group-rounded';
				scope.$searchButtonClasses = 'btn-default';
				angular.forEach(['formClasses', 'inputGroupClasses', 'formControlClasses', 'searchButtonClasses'], function (val, key) {
					attr[val] && attr.$observe(val, function (newVal) {
						newVal && (scope['$' + val] = newVal)
					})
				})
				scope.$searchPlaceholder = attr.searchPlaceholder || 'search...';
				var fileds = [];
				if (attr.searchFields) {
					fileds = attr.searchFields.split(',')
				}
				if (attr.autoSearch && (attr.autoSearch == true) || (attr.autoSearch == 'true')) {
					scope.$watch('searchTerm', function (newValue, oldValue) {
						newValue && scope.$searchTable(); !newValue && oldValue && scope.$clearSearch();
					})
				}
				scope.$clearSearch = function () {
					scope.searchTerm = '';
					controller.refresh();
				}
				scope.$searchTable = function (value) {
					if (scope.searchTerm && (fileds.length || controller.$options.remotePaging)) {
						controller.searchTable(fileds, scope.searchTerm);
					}
				}


			}
		};
	}])

'use strict';
angular.module('ngQuantum.pageable.search')
	.run(['$templateCache', function ($templateCache) {
		$templateCache.put('pageable/tablesearch.tpl.html',
			'<form name="tableSearchForm" class="pageable-search-form" ng-class="$formClasses" ng-submit="$searchTable(searchTerm)">'
			+ '<div class="input-group" ng-class="$inputGroupClasses">'
			+ '<div class="form-control" ng-class="$formControlClasses">'
			+ '<input type="text" ng-model="searchTerm"  class="pageable-search-input" placeholder="{{$searchPlaceholder || \'search\'}}">'
			+ '<span  ng-show="searchTerm"  class="titip-top clear-icon" data-title="Clear filter" ng-click="$clearSearch()"><i class="fic fu-backspace"></i></span>'
			+ '</div>'
			+ '<span class="input-group-btn">'
			+ '<button class="btn" ng-class="$searchButtonClasses" type="submit"><span class="fic fu-search"></span></button>'
			+ '</span>'
			+ '</div>'
			+ '</form>'
		);
	}])
'use strict';
angular.module('ngQuantum.pageable.sorting', [])
	.directive('nqColumnSort', [function () {
		return {
			restrict: 'A',
			require: '^nqPageable',
			link: function (scope, element, attr, controller) {
				var direction = attr.direction || 'asc';
				var field = attr.nqColumnSort, toggle = false, template;

				if (field) {
					if (angular.isDefined(attr.useTemplate)) {
						element.css('position', 'relative')
						template = angular.element('<span class="column-sorting"><span class="asc-icon"></span><span class="desc-icon"></span></span>');
						element.append(template)
						toggle = true;
					}
					element.on('click', function () {
						scope.$apply(function () {
							controller.sortTable(field, direction)
						})
						if (toggle) {
							var dirClass = "sort-" + direction;
							direction = direction == 'asc' ? 'desc' : 'asc';
							if (controller.$options.sortingMode !== 'multiple') {
								var cont = element.closest('.pageable-container');
								angular.element(cont.find('.sort-asc')).removeClass('sort-asc');
								angular.element(cont.find('.sort-desc')).removeClass('sort-desc');

							}
							else {
								element.removeClass("sort-" + direction)
							}
							element.addClass(dirClass)

						}
					})
				}


			}
		};
	}])
'use strict';
angular.module('ngQuantum.pageable.zeroresult', [])
	.directive('nqZeroResult', [function () {
		return {
			restrict: 'A',
			templateUrl: function (element, attr) {
				if (angular.isDefined(attr.noTemplate))
					return false;
				if (angular.isDefined(attr.templateUrl))
					return attr.templateUrl;
				return 'pageable/zeroresult.tpl.html'
			},
			require: '^nqPageable',
			link: function (scope, element, attr, controller) {
				element.addClass("pageable-zero-result");
				angular.forEach(['zeroTitle', 'zeroDescription'], function (val, key) {
					attr[val] && attr.$observe(val, function (newVal) {
						newVal && (scope['$' + val] = newVal)
					})
				})
				scope.$watch('totalResult', function (newVal, oldVal) {
					if (newVal) {
						element.removeClass('visible')
						controller.tableElement && controller.tableElement.show();
						controller.$container && controller.$container.removeClass('no-result-found')
					} else {
						controller.tableElement && controller.tableElement.hide();
						controller.$container && controller.$container.addClass('no-result-found')
						element.addClass('visible')
					}
				})

			}
		};
	}])
'use strict';
angular.module('ngQuantum.pageable.zeroresult')
	.run(['$templateCache', function ($templateCache) {
		'use strict';
		$templateCache.put('pageable/zeroresult.tpl.html',
			'<div class="zero-result-inner">'
			+ '<h1 class="zero-title" nq-bind="$zeroTitle || \'No result found.\'"></h1>'
			+ '<p nq-bind="$zeroDescription || \'There is no data to displayed according to your configuration or filter...\'"></p>'
			+ '</div>'
		);
	}])

'use strict';
angular.module('ngQuantum.pageable', [
	'ngQuantum.pageable.factory',
	'ngQuantum.pageable.directives',
	'ngQuantum.pageable.pager',
	'ngQuantum.pageable.pagination',
	'ngQuantum.pageable.pagesize',
	'ngQuantum.pageable.search',
	'ngQuantum.pageable.sorting',
	'ngQuantum.pageable.zeroresult',
	'ngQuantum.pageable.blocker',
	'ngQuantum.pageable.editing',
	'ngQuantum.pageable.results',
	'ngQuantum.pageable.scroll'
])

'use strict';
angular.module('ngQuantum', [
	'ngQuantum.directives',
	'ngQuantum.tooltip',
	'ngQuantum.aside',
	'ngQuantum.dropdown',
	'ngQuantum.modal',
	'ngQuantum.modalBox',
	'ngQuantum.alert',
	'ngQuantum.popover',
	'ngQuantum.button',
	'ngQuantum.loading',
	'ngQuantum.loadingButton',
	'ngQuantum.tabset',
	'ngQuantum.carousel',
	'ngQuantum.collapse',
	'ngQuantum.select',
	'ngQuantum.datepicker',
	'ngQuantum.scrollbar',
	'ngQuantum.colorpicker',
	'ngQuantum.switchButton',
	'ngQuantum.slider',
	'ngQuantum.pageable'
]);